Amazon S3 Змінити назву файлу для завантаження


101

У мене є файли, що зберігаються на S3 з ідентифікатором GUID як ім'я ключа.

Я використовую попередньо підписану URL-адресу для завантаження відповідно до S3 REST API

Я зберігаю оригінальне ім’я файлу у власній базі даних. Коли користувач натискає, щоб завантажити файл із моєї веб-програми, я хочу повернути його оригінальне ім’я, але наразі все, що вони отримують, - це GUID . Як я можу цього досягти?

Мій веб-додаток працює у Salesforce, тому я не маю великого контролю, щоб робити відповідь. Перенаправляє весь файл, що завантажується, на веб-сервер, а потім перейменовує його через обмеження адміністратора.

Чи є якийсь переспрямування HTML, метаоновлення, Javascript, яким я можу скористатися? Чи є якийсь спосіб змінити ім'я файлу для завантаження для S3 (єдине, що я можу придумати, це обробка об’єкта під новою назвою, його завантаження та видалення).

Я хочу уникнути створення сегмента для кожного користувача, оскільки у нас буде багато користувачів, і все ще не гарантується, що кожен файл у кожному сегменті буде мати унікальну назву

Будь-які інші рішення?


6
Ще одне правомірне ТА питання, яке закрите як поза темою! Питання та відповіді теж мають більше голосів, ніж переважна більшість звичайних питань / відповідей ...
DeepSpace101

Так, очевидно, важливіше, щоб ми намагалися організувати речі дещо довільно, зважаючи на те, що це не гарантовано матиме сенс у майбутньому чи навіть зараз. Що траплялося, коли люди просто отримували задоволення від запитань і відповідей на питання, пов’язані з індустрією програмного забезпечення? Хто насправді знаходить відповідь завдяки цій організації? Хто вважає, що будь-яка організаційна структура програмного забезпечення є послідовною та чітко визначеною у всій галузі? Без цього чіткого визначення, яке триватиме значну кількість часу, організація - це досить дурна втрата часу ...
Дерек Ліц,

1
Я знайшов цю відповідь, у мене немає проблем з цією організацією.
Ісая Тернер

Відповіді:


83

Я думаю, ваш хрест опублікував ці питання на форумі Amazon S3 , але заради інших я хотів би розмістити тут відповідь:

Якщо для кожного об'єкта S3 існує лише одне "ім'я користувача", тоді ви можете встановити заголовок Content-Disposition у своєму файлі s3, щоб встановити ім'я файлу для завантаження: Content-Disposition: вкладення; ім'я файлу = foo.bar

Справедливості заради хотілося б зазначити, що не я давав правильну відповідь на форумі Amazon, і всі кредити повинні надходити Коліну Родсу ;-)


так дякую за нагадування. Інша життєво важлива інформація - це додавання Content-Disposition, яка враховує регістр і НЕ потрібна в префіксі x-amz.
Daveo

3
Погляньте на відповідь нижче, оскільки з січня 2011 року це також можливо на основі запиту GET. Тож можна мати скільки завгодно «імен файлів користувачів».
fabi

2
Мені потрібно було додати лапки в ім'я файлу, щоб це працювало, тому моїм заголовком було: Content-Disposition: attachment; filename = "foo.bar"
nathancahill

1
У c #: request.ResponseHeaderOverrides.ContentDisposition = "вкладення; ім'я файлу = foo.bar";
Амір М

2
Ви можете замінити заголовки відповідей на льоту:https://...example.txt?response-content-disposition=attachment;filename=foo.bar
alaster

46

Хоча прийнята відповідь є правильною, я вважаю її дуже абстрактною та важкою для використання.

Ось фрагмент коду node.js, який вирішує заявлену проблему. Я раджу виконувати його як лямбду AWS для створення попередньо підписаної URL-адреси.

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

}

Зверніть увагу на ResponseContentDispositionатрибут paramsоб’єкта, який перейшов у s3.getSignedUrlфункцію.

Більше інформації в документі функції getObject за адресою http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property


Можливо, це не очевидно, я спробую пояснити краще. Ідея полягає в тому, що я зберігаю список імен завантажених файлів у базі даних, а потім, коли хтось хоче його завантажити, я виконую лямбду з originalFilenameпараметром as.
Павел,


3

Для Java AWS SDK нижче фрагмента коду слід виконати цю роботу:

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

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

generatePresignedUrlRequest.setResponseHeaders(responseHeaders);

3

З C # за допомогою 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);

0

У мене така сама проблема, я вирішив це, встановивши заголовок http "content-disposition", одночасно надсилаючи файл на S3, версія SDK - AWS SDK для PHP 3.x. ось документ http://docs.amazonaws.cn/en_us/aws-sdk-php/latest/api-s3-2006-03-01.html#putobject

шматок мого коду

    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

Це виглядає так: response_content_disposition є недокументованим у методі presigned_url. Це те, що мені вдалося

    signer = Aws::S3::Presigner.new
    signer.presigned_url(:get_object, bucket: @bucket, key: filename, 
    response_content_disposition: "attachment; filename =#{new_name}")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.