キー名としてGUIDを使用してS3にファイルを保存しています。
S3 REST API に従って、事前に署名されたURLを使用してダウンロードしています
元のファイル名を自分のデータベースに保存します。ユーザーがWebアプリケーションからファイルをクリックしてダウンロードするとき、元のファイル名を返したいのですが、現在取得できるのはGUIDだけです。どうすればこれを達成できますか?
私のWebアプリはsalesforceにあるので、response.redirectsですべてのファイルをWebサーバーにダウンロードし、ガバナーの制限によりファイル名を変更することはあまりできません。
使用できるHTMLリダイレクト、メタリフレッシュ、Javascriptがありますか? S3のダウンロードファイル名を変更する方法はありますか(考えられる唯一のことは、オブジェクトを新しい名前にコピーし、ダウンロードしてから削除することです)。
多くのユーザーが存在し、各バケット内の各ファイルに一意の名前があることを保証しないため、ユーザーごとにバケットを作成することは避けたい
他のソリューションはありますか?
あなたのクロスがこの質問を Amazon S3フォーラム に投稿したと思いますが、他の人のためにここに答えを投稿したいと思います:
各S3オブジェクトに「ユーザーファイル名」が1つしかない場合、s3ファイルにContent-Dispositionヘッダーを設定して、ダウンロードファイル名を設定できます。Content-Disposition:attachment; filename = foo.bar
公平を期すために、Amazonフォーラムで正しい答えを提供するのは私ではなく、すべてのクレジットはColin Rhodesに送られるべきであることに言及したいと思います;-)
受け入れられた答えは正しいですが、私はそれが非常に抽象的であり、利用するのが難しいと思います。
上記の問題を解決する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...]
}
s3.getSignedUrl
関数に渡されるResponseContentDisposition
オブジェクトのparams
属性に注意してください。
http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property のgetObject関数ドキュメントの詳細情報
2011年1月上旬、S3はリクエストヘッダーのオーバーライドを追加しました。この機能により、個々のリクエストのContent-Dispositionヘッダーを「動的に」変更できます。
詳細については、S3 オブジェクトの取得に関するドキュメント を参照してください。
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);
AWSSDKを使用するC#では、
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
{
BucketName = BucketName,
Key = Key,
Expires = DateTime.Now.AddMinutes(25)
};
request.ResponseHeaderOverrides.ContentDisposition = $"attachment; filename={FileName}";
var url = s3Client.GetPreSignedURL(request);
: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}")
私は同じ問題を抱えています。S3にファイルを送信するときにhttpヘッダー「content-disposition」を設定することで解決しました。SDKバージョンはAWS SDK for 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)
{
...
}
}