AmazonS3ファイルのダウンロード名を変更する


102

キー名としてGUIDを使用してS3にファイルを保存しています。

S3 RESTAPIに従ってダウンロードするために事前に署名されたURLを使用しています

元のファイル名を自分のデータベースに保存します。ユーザーがクリックしてWebアプリケーションからファイルをダウンロードすると、元のファイル名を返したいのですが、現在取得できるのはGUIDだけです。どうすればこれを達成できますか?

私のWebアプリはセールスフォースにあるため、response.redirectsを実行するための制御があまりありません。ファイルをWebサーバーにダウンロードしてから、ガバナーの制限により名前を変更します。

使用できるHTMLリダイレクト、メタリフレッシュ、Javascriptはありますか?S3のダウンロードファイル名を変更する方法はありますか(私が考えることができる唯一のことは、オブジェクトを新しい名前にコピーし、ダウンロードしてから削除することです)。

多くのユーザーがいるため、ユーザーごとにバケットを作成することは避けたいと思います。それでも、各バケットに含まれる各ファイルに一意の名前が付けられる保証はありません。

他の解決策はありますか?


7
トピック外としてクローズされたもう1つの正当なSO質問!質問と回答も、通常の質問/回答の大多数よりも多くの票を獲得しています...
DeepSpace101 2013

はい、将来または現在でも意味があることが保証されていないという事実に直面して、物事をいくらか恣意的に整理しようとすることが明らかにもっと重要です。人々がソフトウェア業界に関連する質問をしたり答えたりするのを楽しんだとき、どうなりましたか?この組織のおかげで、誰が実際に答えを見つけますか?業界全体で一貫性があり、明確に定義されているソフトウェアの組織構造を誰が見つけますか?整理にかなりの時間がかかるこの明確な定義がなければ、それはかなり愚かな時間の無駄です...
Derek Litz 2013

1
私はこの答えを見つけました、私はこの組織に問題はありません。
アイザイアターナー

回答:


83

あなたのクロスがこの質問をAmazonS3フォーラムに投稿したと思いますが、他の人のために、ここに回答を投稿したいと思います。

S3オブジェクトごとに「ユーザーファイル名」が1つしかない場合は、s3ファイルにContent-Dispositionヘッダーを設定して、ダウンロードファイル名を設定できます。Content-Disposition:attachment; filename = foo.bar

公平を期すために、Amazonフォーラムで正しい答えを提供するのは私ではなく、すべてのクレジットはColinRhodesに送られるべきです;-)


はい、私に思い出させてくれてありがとう。もう1つの重要な情報は、Content-Dispositionを追加するときに、大文字と小文字が区別され、x-amzプレフィックスを必要としないことです。
Daveo 2010

3
以下の回答をご覧ください。2011年1月以降、GETリクエストごとに実行することもできます。したがって、必要な数の「ユーザーファイル名」を持つことができます。
ファビ2015

2
これを機能させるには、ファイル名に引用符を追加する必要があったため、ヘッダーは次のとおりでした。Content-Disposition:attachment; filename = "foo.bar"
nathancahill 2015

1
C#の場合:request.ResponseHeaderOverrides.ContentDisposition = "attachment; filename = foo.bar";
アミールM

2
その場で応答ヘッダーをオーバーライドできます。https://...example.txt?response-content-disposition=attachment;filename=foo.bar
alaster19年

46

受け入れられた答えは正しいですが、私はそれが非常に抽象的で利用するのが難しいと思います。

これは、述べられた問題を解決するnode.jsコードの一部です。事前に署名されたURLを生成するために、AWSLambdaとして実行することをお勧めします。

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属性に注意してください。paramss3.getSignedUrl

詳細については、http: //docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-propertyのgetObject関数ドキュメントを参照してください。


はっきりしないかもしれませんが、もっとよく説明しようと思います。アップロードされたファイルの名前のリストをデータベースに保持し、誰かがそれをダウンロードしたいときにoriginalFilename、パラメーターとしてラムダを実行するという考え方です。
Pawel 2018


3

以下のJavaAWS 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

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);

0

同じ問題があります。ファイルをS3に送信するときにhttpヘッダー「content-disposition」を設定することで解決しました。SDKバージョンはAWSSDK for PHP3.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}")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.