Amazon S3 파일 다운로드 이름 변경


103

키 이름으로 GUID를 사용하여 S3에 파일이 저장되어 있습니다.

사전 서명 된 URL을 사용하여 S3 REST API에 따라 다운로드하고 있습니다.

내 데이터베이스에 원래 파일 이름을 저장합니다. 사용자가 내 웹 응용 프로그램에서 파일을 다운로드하기 위해 클릭하면 원래 파일 이름을 반환하고 싶지만 현재 얻는 것은 GUID뿐입니다 . 어떻게하면 되나요?

내 웹 앱이 세일즈 포스에 있으므로 response.redirects를 수행 할 수있는 권한이 많지 않습니다. 모든 파일을 웹 서버로 다운로드 한 다음 관리자 제한으로 인해 이름을 바꿉니다.

HTML 리디렉션, 메타 새로 고침, Javascript를 사용할 수 있습니까? S3의 다운로드 파일 이름을 변경할 수있는 방법이 있습니까? (내가 생각할 수있는 유일한 방법은 객체를 새 이름으로 복사하고 다운로드 한 다음 삭제하는 것입니다).

사용자가 많지만 각 버킷에있는 각 파일이 고유 한 이름을 가질 것이라는 보장은 없으므로 사용자별로 버킷을 만드는 것을 피하고 싶습니다.

다른 해결책이 있습니까?


7
주제에서 벗어난 또 다른 합법적 인 질문! 질문과 답변은 ... 일반적인 질문 / 답변의 대부분보다 더 많은 표가 너무
DeepSpace101

예, 우리가 미래 나 지금도 의미가 있다고 보장 할 수 없다는 사실을 감안하여 다소 임의적으로 정리하는 것이 더 중요합니다. 사람들이 소프트웨어 산업과 관련된 질문을하고 대답하는 것을 즐겼을 때 무슨 일이 일어 났습니까? 이 조직 때문에 실제로 누가 답을 찾습니까? 소프트웨어의 조직 구조가 업계 전반에 걸쳐 일관성 있고 명확하게 정의 된 조직은 누구입니까? 그것은 시간이 상당히 바보 낭비 조직에 상당한 시간이 지난 것이 명확한 정의 ... 없음
데릭 리츠

1
이 답변을 찾았습니다.이 조직에는 아무런 문제가 없습니다.
Isaiah Turner

답변:


84

나는 당신의 십자가가 Amazon S3 포럼 에이 질문을 게시했다고 생각 하지만 다른 사람들을 위해 여기에 답변을 게시하고 싶습니다.

각 S3 객체에 대해 하나의 "사용자 파일 이름"만있는 경우 s3 파일에 Content-Disposition 헤더를 설정하여 다운로드 파일 이름을 설정할 수 있습니다. Content-Disposition : attachment; filename = foo.bar

공정성을 위해 Amazon 포럼에서 정답을 제공하는 것은 제가 아니었고 모든 크레딧은 Colin Rhodes에 가야한다는 점을 언급하고 싶습니다 ;-)


네 상기시켜 주셔서 감사합니다. 중요한 정보의 다른 부분은 Content-Disposition을 추가 할 때 대소 문자를 구분하며 x-amz 접두어에 필요하지 않습니다.
Daveo 2010

3
아래 답변을 살펴보십시오. 2011 년 1 월부터 GET 요청 단위로도 가능합니다. 따라서 원하는만큼 "사용자 파일 이름"을 가질 수 있습니다.
fabi

2
이 작업을 수행하려면 파일 이름에 따옴표를 추가해야했기 때문에 헤더는 다음과 같습니다. Content-Disposition : attachment; filename = "foo.bar"
nathancahill 2015

1
C #에서 : request.ResponseHeaderOverrides.ContentDisposition = "attachment; filename = foo.bar";
Amir M

2
즉석에서 응답 헤더를 재정의 할 수 있습니다.https://...example.txt?response-content-disposition=attachment;filename=foo.bar
alaster aug

47

받아 들여지는 대답은 정확하지만 매우 추상적이며 활용하기가 어렵습니다.

여기에 언급 된 문제를 해결하는 node.js 코드가 있습니다. 미리 서명 된 Url을 생성하려면 AWS Lambda로 실행하는 것이 좋습니다.

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 함수 문서에 대한 자세한 정보


분명하지 않을 수도 있지만 더 잘 설명하려고 노력할 것입니다. 아이디어는 데이터베이스에 업로드 된 파일의 이름 목록을 유지하고 누군가가 그것을 다운로드하고 싶을 때 originalFilenameas 매개 변수로 람다를 실행한다는 것 입니다.
Pawel

27

2011 년 1 월 초 S3는 요청 헤더 재정의를 추가했습니다. 이 기능을 사용하면 개별 요청에 대한 Content-Disposition 헤더를 '동적으로'변경할 수 있습니다.

자세한 내용은 객체 가져 오기에 대한 S3 설명서 를 참조하십시오.


3

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

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 버전은 PHP 3.x 용 AWS SDK입니다. 여기 문서 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}")

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"
        },
    )
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.