Amazon S3 Ubah nama unduhan file

103

Saya memiliki file yang disimpan di S3 dengan GUID sebagai nama kuncinya.

Saya menggunakan URL yang telah ditandatangani sebelumnya untuk mengunduh sesuai dengan S3 REST API

Saya menyimpan nama file asli di Database saya sendiri. Ketika pengguna mengklik untuk mengunduh file dari aplikasi web saya, saya ingin mengembalikan nama file aslinya, tetapi saat ini yang mereka dapatkan hanyalah GUID . Bagaimana saya bisa mencapai ini?

Aplikasi web saya ada di bagian penjualan jadi saya tidak memiliki banyak kendali untuk melakukan respons. Mengalihkan semua mengunduh file ke server web lalu mengganti namanya karena batasan gubernur.

Apakah ada beberapa pengalihan HTML, penyegaran meta, Javascript yang dapat saya gunakan? Apakah ada cara untuk mengubah nama file unduhan untuk S3 (satu-satunya hal yang dapat saya pikirkan adalah mengatasi objek ke nama baru, mengunduhnya, lalu menghapusnya).

Saya ingin menghindari pembuatan keranjang per pengguna karena kita akan memiliki banyak pengguna dan tetap tidak ada jaminan setiap file yang ada di setiap keranjang akan memiliki nama yang unik

Ada solusi lain?

Daveo
sumber
7
Pertanyaan SO lain yang sah yang ditutup sebagai di luar topik! Pertanyaan dan jawaban juga memiliki lebih banyak suara daripada sebagian besar pertanyaan / jawaban biasa ...
DeepSpace101
Ya, jelas lebih penting bagi kita untuk mencoba mengatur hal-hal yang agak sewenang-wenang mengingat fakta bahwa hal itu tidak dijamin masuk akal di masa depan atau bahkan sekarang. Apa yang terjadi ketika orang-orang asyik bertanya dan menjawab pertanyaan yang berkaitan dengan industri perangkat lunak? Siapa yang menemukan jawabannya karena organisasi ini? Siapa yang menemukan struktur organisasi dalam perangkat lunak yang konsisten dan didefinisikan dengan jelas di seluruh industri? Tanpa definisi yang jelas ini yang akan memakan banyak waktu untuk mengaturnya adalah buang-buang waktu yang cukup bodoh ...
Derek Litz
1
Saya menemukan jawaban ini, saya tidak punya masalah dengan organisasi ini.
Isaiah Turner

Jawaban:

84

Saya kira salib Anda memposting pertanyaan ini ke forum Amazon S3 , tetapi demi orang lain saya ingin memposting jawabannya di sini:

Jika hanya ada satu "nama file pengguna" untuk setiap objek S3, maka Anda dapat mengatur header Content-Disposition pada file s3 Anda untuk mengatur nama file download: Content-Disposition: attachment; filename = foo.bar

Demi keadilan, saya ingin menyampaikan bahwa bukan saya yang memberikan jawaban yang benar di forum Amazon dan semua kredit harus diberikan kepada Colin Rhodes ;-)

cloudberryman
sumber
ya terima kasih telah mengingatkan saya. Bagian lain dari informasi penting adalah saat menambahkan Disposisi Konten, ini peka huruf besar-kecil dan TIDAK perlu di awalan x-amz.
Daveo
3
Lihatlah jawaban di bawah ini, sejak Januari 2011 juga dimungkinkan berdasarkan permintaan GET. Jadi mungkin untuk memiliki "nama file pengguna" sebanyak yang Anda inginkan.
fabi
2
Saya perlu menambahkan tanda kutip pada nama file agar ini berfungsi, jadi header saya adalah: Content-Disposition: attachment; filename = "foo.bar"
nathancahill
1
Dalam c #: request.ResponseHeaderOverrides.ContentDisposition = "lampiran; nama file = foo.bar";
Amir M
2
Anda dapat mengganti tajuk tanggapan dengan cepat:https://...example.txt?response-content-disposition=attachment;filename=foo.bar
alaster
48

Meskipun jawaban yang diterima benar, saya merasa sangat abstrak dan sulit untuk digunakan.

Berikut adalah potongan kode node.js yang memecahkan masalah yang disebutkan. Saya menyarankan untuk menjalankannya sebagai AWS Lambda untuk menghasilkan Url yang sudah ditandatangani sebelumnya.

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...]

}

Harap perhatikan ResponseContentDispositionatribut paramsobjek yang dilewatkan ke dalam s3.getSignedUrlfungsi.

Informasi lebih lanjut di bawah dokumen fungsi getObject di http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

Pawel
sumber
Mungkin belum jelas, saya akan coba jelaskan lebih baik. Idenya adalah saya menyimpan daftar nama file yang diunggah dalam database, dan kemudian ketika seseorang ingin mengunduhnya saya menjalankan lambda dengan originalFilenameparameter as.
Pawel
27

Pada awal Januari 2011 S3 menambahkan penggantian header permintaan. Fungsionalitas ini memungkinkan Anda untuk 'secara dinamis' mengubah header Content-Disposition untuk setiap permintaan.

Lihat dokumentasi S3 tentang mendapatkan objek untuk lebih jelasnya.

Uriah Carpenter
sumber
4

Dengan C # menggunakan AWSSDK,

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

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

var url = s3Client.GetPreSignedURL(request);
hkutluay.dll
sumber
3

Untuk Java AWS SDK di bawah Code Snippet harus melakukan pekerjaan:

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

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

generatePresignedUrlRequest.setResponseHeaders(responseHeaders);
Abhishek Basak
sumber
0

Saya memiliki masalah yang sama, saya menyelesaikannya dengan mengatur http header "content-disposition" saat mengirimkan file ke S3, versi SDK adalah AWS SDK untuk PHP 3.x. berikut adalah dokumennya http://docs.amazonaws.cn/en_us/aws-sdk-php/latest/api-s3-2006-03-01.html#putobject

sepotong kode saya

    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)
        {
            ...
        }
    }
mok
sumber
0

Sepertinya: response_content_disposition tidak terdokumentasi dalam metode presigned_url. Inilah yang berhasil bagi saya

    signer = Aws::S3::Presigner.new
    signer.presigned_url(:get_object, bucket: @bucket, key: filename, 
    response_content_disposition: "attachment; filename =#{new_name}")
Chris Mcdonald
sumber
0

Menggunakan python dan boto v2:

    conn = boto.connect_s3(
        AWS_ACCESS_KEY_ID,
        AWS_SECRET_ACCESS_KEY,
        host=settings.AWS_S3_HOST,
    )
    b = conn.get_bucket(BUCKET_NAME)
    key = b.get_key(path)
    url = key.generate_url(
        expires_in=60 * 60 * 10,  # expiry time is in seconds
        response_headers={
            "response-content-disposition": "attachment; filename=foo.bar"
        },
    )
Udi
sumber