Amazon S3 Dosya indirme adını değiştirin


102

Anahtar adı olarak bir GUID ile S3'te depolanan dosyalarım var.

S3 REST API'ye göre indirmek için önceden imzalanmış bir URL kullanıyorum

Orijinal dosya adını kendi Veritabanımda saklıyorum. Bir kullanıcı web uygulamamdan bir dosya indirmek için tıkladığında , orijinal dosya adını döndürmek istiyorum, ancak şu anda aldıkları tek şey bir GUID . Bunu nasıl başarabilirim?

Web uygulamam satış ekibinde olduğu için yanıt vermek için fazla kontrole sahip değilim. Tüm indirilen dosyayı web sunucusuna yönlendiriyor ve ardından vali sınırlamaları nedeniyle yeniden adlandırıyor.

Kullanabileceğim bir miktar HTML yönlendirmesi, meta yenileme, Javascript var mı? S3 için indirme dosyası adını değiştirmenin bir yolu var mı (aklıma gelen tek şey nesneyi yeni bir adla değiştirmek, indirmek ve sonra silmek).

Çok sayıda kullanıcımız olacağından ve yine de her gruptaki her dosyanın benzersiz bir ada sahip olacağına dair hiçbir garanti olmadığından, kullanıcı başına grup oluşturmaktan kaçınmak istiyorum

Başka çözüm var mı?


7
Konu dışı olarak kapatılan başka bir okunaklı SO sorusu! Soru ve cevaplar da normal soruların / cevapların büyük çoğunluğundan daha fazla oy
içeriyor

Evet, gelecekte ve hatta şimdi mantıklı olmasının garanti edilmediği gerçeği karşısında işleri biraz keyfi bir şekilde düzenlemeye çalışmamız çok daha önemli. İnsanlar yazılım endüstrisiyle ilgili soru sorup cevaplarken eğlenirken ne oldu? Bu organizasyon sayesinde cevabı gerçekten kim buluyor? Yazılımda herhangi bir organizasyon yapısını sektör genelinde tutarlı ve açıkça tanımlanmış kim bulur? Organize etmek için önemli miktarda zaman sürecek bu net tanım olmadan, oldukça aptalca bir zaman kaybı olur ...
Derek Litz

1
Bu cevabı buluyorum, bu organizasyonla bir sorunum yok.
Isaiah Turner

Yanıtlar:


83

Sanırım çaprazınız bu soruyu Amazon S3 forumunda yayınladı , ancak başkalarının iyiliği için cevabı buraya göndermek istiyorum:

Her S3 nesnesi için yalnızca bir "kullanıcı dosya adı" varsa, indirme dosya adını ayarlamak için s3 dosyanızdaki Content-Disposition başlığını ayarlayabilirsiniz: Content-Disposition: attachment; dosyaadı = foo.bar

Adil olmak adına, Amazon forumunda doğru cevabı vermenin ben olmadığımı ve tüm kredilerin Colin Rhodes'a gitmesi gerektiğini belirtmek isterim ;-)


evet hatırlattığın için teşekkür ederim. Diğer önemli bilgi parçası, Content-Disposition eklerken, büyük / küçük harfe duyarlıdır ve x-amz önekine gerek YOKTUR.
Daveo

3
Aşağıdaki cevaba bir göz atın, Ocak 2011'den bu yana GET başına talep bazında da mümkündür. Böylece istediğiniz kadar "kullanıcı dosya adına" sahip olmak mümkündür.
fabi

2
Bunun çalışması için dosya adına tırnak işaretleri eklemem gerekiyordu, bu yüzden başlığım şöyleydi: Content-Disposition: attachment; filename = "foo.bar"
nathancahill

1
C #: request.ResponseHeaderOverrides.ContentDisposition = "attachment; dosyaadı = foo.bar";
Amir M

2
Yanıt başlıklarını anında geçersiz kılabilirsiniz:https://...example.txt?response-content-disposition=attachment;filename=foo.bar
önce

46

Kabul edilen cevap doğru olsa da, onu çok soyut ve kullanması zor buluyorum.

Belirtilen sorunu çözen bir node.js kodu aşağıda verilmiştir. Önceden imzalanmış URL oluşturmak için AWS Lambda olarak çalıştırmanızı öneririm.

var AWS = require('aws-sdk');
var s3 = new AWS.S3({
    signatureVersion: 'v4'
});
const s3Url = process.env.BUCKET;

module.exports.main = (event, context, callback) => {
var s3key = event.s3key
var originalFilename = event.originalFilename

var url = s3.getSignedUrl('getObject', {
        Bucket: s3Url,
        Key: s3key,
        Expires: 600,
        ResponseContentDisposition: 'attachment; filename ="' + originalFilename + '"'
    });

[... rest of Lambda stuff...]

}

Lütfen, işleve aktarılan nesnenin ResponseContentDispositionniteliğine dikkat edin .paramss3.getSignedUrl

Http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property adresindeki getObject işlevi dokümanı altında daha fazla bilgi


Belkide açık değil, daha iyi açıklamaya çalışacağım. Buradaki fikir, yüklenen dosyaların isimlerinin listesini veritabanında tutmam ve sonra birisi onu indirmek istediğinde lambda'yı originalFilenameas parametresiyle çalıştırmam .
Pawel

27

Ocak 2011'in başlarında S3, istek üstbilgisi geçersiz kılmaları ekledi. Bu işlevsellik, tek tek istekler için Content-Disposition başlığını 'dinamik olarak' değiştirmenize olanak tanır.

Daha fazla ayrıntı için nesne alma ile ilgili S3 belgelerine bakın.


3

Java AWS SDK için aşağıdaki Kod Parçacığı şu işi yapmalıdır:

GeneratePresignedUrlRequest generatePresignedUrlRequest = 
                new GeneratePresignedUrlRequest(s3Bucket, objectKey)
                .withMethod(HttpMethod.GET)
                .withExpiration(getExpiration());

ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
responseHeaders.setContentDisposition("attachment; filename =\"" + fileName + "\"");

generatePresignedUrlRequest.setResponseHeaders(responseHeaders);

3

AWSSDK kullanarak C # ile,

GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
{
    BucketName = BucketName,
    Key = Key,
    Expires = DateTime.Now.AddMinutes(25) 
};

request.ResponseHeaderOverrides.ContentDisposition = $"attachment; filename={FileName}";

var url = s3Client.GetPreSignedURL(request);

0

Ben de aynı sorunu yaşıyorum, dosyayı S3'e gönderirken "content-disposition" ayarlı http başlığı ile çözdüm, SDK sürümü PHP 3.x için AWS SDK'dır. işte belge http://docs.amazonaws.cn/en_us/aws-sdk-php/latest/api-s3-2006-03-01.html#putobject

kodumun bir parçası

    public function __construct($config) 
    {
        $this->handle = new S3Client([
            'credentials' => array(
                'key' => $config['key'],
                'secret' => $config['secret'],
            ),
            ...
        ]);

        ...
    }

    public function putObject($bucket, $object_name, $source_file, $content_type = false, $acl = 'public-read', $filename = '')
    {
        try {
            $params = [
                'Bucket'      => $bucket,
                'Key'         => $object_name,
                'SourceFile'  => $source_file,
                'ACL'         => $acl,
            ];

            if ($content_type) $params['ContentType'] = $content_type;
            if ($filename) $params['ContentDisposition'] = 'attachment; filename="' . $filename . '"';

            $result = $this->handle->putObject($params);

            ...
        }
        catch(Exception $e)
        {
            ...
        }
    }

0

Şuna benzer: response_content_disposition, presigned_url yönteminde belgelenmemiş. Bu benim için çalıştı

    signer = Aws::S3::Presigner.new
    signer.presigned_url(:get_object, bucket: @bucket, key: filename, 
    response_content_disposition: "attachment; filename =#{new_name}")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.