Amazon S3更改文件下载名称

时间:2010-04-09 22:43:04

标签: rest amazon-s3 amazon-web-services

我的文件存储在S3上,GUID作为密钥名称。

我使用预先签名的网址按照S3 REST API

进行下载

我将原始文件名存储在我自己的数据库中。当用户单击从我的Web应用程序下载文件时我想返回其原始文件名,但目前他们获得的只是一个GUID 。我怎样才能做到这一点?

我的网络应用程序在salesforce中,所以我没有太多控制权来做响应。所有人都将文件下载到网络服务器,然后由于州长限制而重命名。

是否有一些HTML重定向,元刷新,我可以使用的Javascript?有没有办法改变S3的下载文件名(我唯一能想到的是将对象复制到新名称,下载,然后删除它)。

我想避免为每个用户创建一个存储桶,因为我们会有很多用户,但仍不能保证每个存储桶中的每个文件都有一个唯一的名称

还有其他解决方案吗?

8 个答案:

答案 0 :(得分:66)

我猜你的十字架已将此问题发布到Amazon S3 forum,但为了其他人,我想在这里发布答案:

如果每个S3对象只有一个“用户文件名”,则可以在s3文件上设置Content-Disposition标头以设置下载文件名: 内容 - 处理:附件;文件名= foo.bar

为了公平起见,我想提一下,不是我在亚马逊论坛上提供正确的答案而且所有的学分都应该归到科林罗德; - )

答案 1 :(得分:21)

2011年1月初,S3添加了请求标头覆盖。此功能允许您“动态”更改单个请求的Content-Disposition标头。

有关详细信息,请参阅S3 documentation on getting objects

答案 2 :(得分:20)

虽然接受的答案是正确的,但我发现它非常抽象,难以利用。

这是一段解决所述问题的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对象的import pygame pygame.init() SIZE = (600,200) screen = pygame.display.set_mode(SIZE) bg_image = None def draw_background(screen): global bg_image if not bg_image: bg_image = pygame.Surface((SIZE)) pygame.draw.rect(bg_image, (175,171,171), [0, 0, 600, 200]) pygame.draw.rect(bg_image, (255,192,0), [200, 0, 200, 200]) ... # Draw whatever you want inside this if body screen.blit(bg_image, (0, 0)) ... class Truck: ... def game_loop(): newTruck = Truck(truck, 0, 50, 1) gameExit = False while not gameExit: for event in pygame.event.get(): if event.type == pygame.QUIT: gameExit = True newTruck.move() draw_background() screen.blit(newTruck.image, newTruck.pos) clock.tick(60) pygame.display.update() game_loop() 属性。

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

下的getObject function doc下的更多信息

答案 3 :(得分:1)

在presigned_url方法中似乎没有记录:response_content_disposition。这就是对我有用的

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

答案 4 :(得分:1)

对于代码段下面的Java AWS开发工具包,该工作应该完成:

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

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

generatePresignedUrlRequest.setResponseHeaders(responseHeaders);

答案 5 :(得分:0)

我遇到了同样的问题,我通过在将文件提交到S3时设置http标头“ content-disposition”来解决它,该SDK版本是适用于PHP 3.x的AWS开发工具包。这是文档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)
        {
            ...
        }
    }

答案 6 :(得分:0)

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

答案 7 :(得分:0)

使用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"
        },
    )