简体   繁体   English

Amazon S3 更改文件下载名称

[英]Amazon S3 Change file download name

I have files stored on S3 with a GUID as the key name.我将文件存储在 S3 上,并以 GUID 作为键名。

I am using a pre signed URL to download as per S3 REST API我正在使用预签名的 URL 按照S3 REST API下载

I store the original file name in my own Database.我将原始文件名存储在我自己的数据库中。 When a user clicks to download a file from my web application I want to return their original file name, but currently all they get is a GUID .当用户单击从我的 web 应用程序下载文件时,我想返回他们的原始文件名,但目前他们得到的只是一个 GUID How can I achieve this?我怎样才能做到这一点?

My web app is in salesforce so I do not have much control to do response.redirects all download the file to the web server then rename it due to governor limitations.我的 web 应用程序位于 salesforce,因此我没有太多控制权来执行 response.redirects,所有文件都下载到 web 服务器,然后由于调控器限制而重命名。

Is there some HTML redirect, meta refresh, Javascript I can use?是否有一些 HTML 重定向、元刷新、Javascript 我可以使用? Is there some way to change the download file name for S3 (the only thing I can think of is coping the object to a new name, downloading it, then deleting it).有什么方法可以更改 S3 的下载文件名(我唯一能想到的就是将 object 改成新名称,下载它,然后删除它)。

I want to avoid creating a bucket per user as we will have a lot of users and still no guarantee each file with in each bucket will have a unique name我想避免为每个用户创建一个存储桶,因为我们会有很多用户,但仍然不能保证每个存储桶中的每个文件都有一个唯一的名称

Any other solutions?还有其他解决方案吗?

I guess your cross posted this questions to Amazon S3 forum , but for the sake of others I'd like to post the answer here:我猜你的交叉将这个问题发布到了Amazon S3 论坛,但为了其他人,我想在这里发布答案:

If there is only ever one "user filename" for each S3 object, then you can set the Content-Disposition header on your s3 file to set the downloading filename:如果每个 S3 对象只有一个“用户文件名”,那么您可以在 s3 文件上设置 Content-Disposition 标头以设置下载文件名:

Content-Disposition: attachment; filename="foo.bar"

For the sake of fairness I'd like to mention that it was not me to provide the right answer on Amazon forum and all credits should go to Colin Rhodes ;-)为了公平起见,我想提一下,在亚马逊论坛上提供正确答案的不是我,所有的功劳都应该归功于 Colin Rhodes ;-)

While the accepted answer is correct I find it very abstract and hard to utilize.虽然接受的答案是正确的,但我发现它非常抽象且难以使用。

Here is a piece of node.js code that solves the problem stated.这是一段解决上述问题的 node.js 代码。 I advise to execute it as the AWS Lambda to generate pre-signed Url.我建议将其作为 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...]

}

Please, take note of ResponseContentDisposition attribute of params object passed into s3.getSignedUrl function.请注意传入s3.getSignedUrl函数的params对象的ResponseContentDisposition属性。

More information under getObject function doc at http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property位于http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property 的getObject 函数文档下的更多信息

In early January 2011 S3 added request header overrides. 2011 年 1 月上旬,S3 添加了请求标头覆盖。 This functionality allows you to 'dynamically' alter the Content-Disposition header for individual requests.此功能允许您“动态”更改单个请求的 Content-Disposition 标头。

See the S3 documentation on getting objects for more details.有关更多详细信息,请参阅有关获取对象的 S3 文档

With C# using AWSSDK,使用 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);

For Java AWS SDK below Code Snippet should do the job:对于下面的 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);

It looks like :response_content_disposition is undocumented in the presigned_url method.看起来 :response_content_disposition 在 presigned_url 方法中没有记录。 This is what worked for me这对我有用

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

Using python and boto v2:使用 python 和 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"
        },
    )

I have the same issue, I solved it by set http header "content-disposition" while submit the file to S3, the SDK version is AWS SDK for PHP 3.x.我有同样的问题,我通过在将文件提交到 S3 时设置 http 标头“content-disposition”来解决它,SDK 版本是 AWS SDK for PHP 3.x。 here is the doc http://docs.amazonaws.cn/en_us/aws-sdk-php/latest/api-s3-2006-03-01.html#putobject这是文档http://docs.amazonaws.cn/en_us/aws-sdk-php/latest/api-s3-2006-03-01.html#putobject

a piece of my code我的一段代码

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

I spent a few hours to find this solution.我花了几个小时找到这个解决方案。

const { CloudFront } = require("aws-sdk");
const url = require("url");

const generateSingedCloudfrontUrl = (path) => {
  const cloudfrontAccessKeyId = process.env.CF_ACCESS_KEY;
  const cloudFrontPrivateKey = process.env.CF_PRIVATE_KEY;
  const formattedKey = `${"-----BEGIN RSA PRIVATE KEY-----"}\n${cloudFrontPrivateKey}\n${"-----END RSA PRIVATE KEY-----"}`;
  const signer = new CloudFront.Signer(cloudfrontAccessKeyId, formattedKey);
  //  12 hours
  const EXPIRY_TIME = 43200000;

  const domain = process.env.CF_DOMAIN;
  const signedUrl = signer.getSignedUrl({
    url: url.format(`https://${domain}/${path}`),
    expires: Math.floor((Date.now() + EXPIRY_TIME) / 1000),
  });
  return signedUrl;
};

const fileName = "myFile.png";
  const result = generateSingedCloudfrontUrl(
    `originals/orgs/originals/MSP/1539087e-02b7-414f-abc8-3542ee0c8420/1644588362499/Screenshot from 2022-02-09 16-29-04..png?response-content-disposition=${encodeURIComponent(
      `attachment; filename=${fileName}`
    )
});

Faced similar issue.面临类似的问题。 Need to generate pre-signed url to download pdf from s3 but with different name other that what present in s3 bucket.需要生成预签名 url 以从 s3 下载 pdf,但名称与 s3 存储桶中存在的名称不同。 This got resolved by using:-这通过使用解决了: -

Using Python boto3使用 Python boto3

file_download_url = client.generate_presigned_url(
ClientMethod = "get_object",
ExpiresIn = 3600,
Params = {
    "Bucket": "s3_bucket_name",
    "Key": "s3_key",
    "ResponseContentDisposition": "attachment; filename=file_name.pdf",
    "ResponseContentType" : "application/pdf"
}

) )

Reference:- https://github.com/boto/boto3/issues/356参考:- https://github.com/boto/boto3/issues/356

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM