Amazon S3
У меня есть файлы, хранящиеся на S3 с идентификатором GUID в качестве имени ключа.
Я использую предварительно подписанный URL для загрузки по S3 REST API
Я сохраняю исходное имя файла в своей собственной базе данных. Когда пользователь нажимает, чтобы загрузить файл из моего веб-приложения , я хочу вернуть исходное имя файла, но в настоящее время все, что они получают, это GUID. Как я могу достичь этого?
Мое веб-приложение работает в salesforce, поэтому у меня нет большого контроля за выполнением response.redirects, все файлы загружаются на веб-сервер, а затем переименовывают его из-за ограничений, присущих губернатору.
Есть ли какая-либо переадресация HTML, мета-обновление, Javascript, который я могу использовать? Есть ли способ изменить имя файла загрузки для S3 (единственное, о чем я могу думать, - это совместить объект с новым именем, загрузить его, а затем удалить его).
Я хочу, чтобы не создавать bucket для каждого пользователя, поскольку у нас будет много пользователей, и все равно нет гарантии, что каждый файл в каждом ведре будет иметь уникальное имя
Любые другие решения?
Ответы
Ответ 1
Я думаю, ваш крест разместил эти вопросы на форуме Amazon S3, но ради других я хотел бы разместить здесь ответ:
Если для каждого объекта S3 существует только одно "имя пользователя", то вы можете установить заголовок Content-Disposition в файле s3, чтобы установить имя файла загрузки:
Content-Disposition: вложение; имя файла = foo.bar
Ради справедливости я хотел бы упомянуть, что я не мог дать правильный ответ на форуме Amazon, и все кредиты должны отправиться в Колин Родос; -)
Ответ 2
Хотя принятый ответ является правильным, я нахожу его очень абстрактным и трудным для использования.
Вот фрагмент кода node.js, который решает указанную проблему. Я советую выполнить его как AWS Lambda для генерации предварительно подписанного 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.
Ответ 3
В начале января 2011 года S3 добавил заголовок заголовка запроса. Эта функциональность позволяет вам "динамически" изменять заголовок Content-Disposition для отдельных запросов.
Подробнее см. документацию S3 для получения объектов.
Ответ 4
Это выглядит так: 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}")
Ответ 5
Для Java AWS SDK ниже Code Snippet должен выполнить эту работу:
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(s3Bucket, objectKey)
.withMethod(HttpMethod.GET)
.withExpiration(getExpiration());
ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
responseHeaders.setContentDisposition("attachment; filename =\"" + fileName + "\"");
generatePresignedUrlRequest.setResponseHeaders(responseHeaders);
Ответ 6
У меня та же проблема, я решил ее, установив 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)
{
...
}
}
Ответ 7
С С# с использованием 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);