Django 作为 S3 代理

sch*_*eck 10 django amazon-s3 django-admin boto amazon-web-services

我使用自定义字段“下载文件”扩展了 ModelAdmin,它是我的 Django 项目中 URL 的链接,例如:

http://www.myproject.com/downloads/1
Run Code Online (Sandbox Code Playgroud)

在那里,我想提供一个存储在 S3 存储桶中的文件。存储桶中的文件不是公开可读的,用户可能无法直接访问它。现在我想

  • 避免必须将文件加载到服务器内存中(这些是多 GB 文件)
  • 避免在服务器上有临时文件

理想的解决方案是让 django 充当代理,将 S3 块直接传输给用户。我使用 boto,但没有找到流式传输块的可能性。有任何想法吗?

谢谢。

jde*_*ace 14

是的,您可以使用 Django 作为代理将您的 S3 文件流式传输给用户。

  1. 为您的文件生成标准的 S3 url。
  2. 使用requests库以流模式获取文件。
  3. 使用 Django 向用户提供原始流。
import requests, boto3
from django.views.generic import View
from django.http.response import HttpResponse

class MediaDownloadView(View):

    def get(self, request, *args, **kwargs):
        s3 = boto3.resource(
            service_name='s3', aws_access_key_id='XXX_AWS_ACCESS_KEY_ID',
            aws_secret_access_key='XXX_AWS_ACCESS_KEY',
        )
        url = s3.meta.client.generate_presigned_url(
            ClientMethod="get_object", ExpiresIn=3600,
            Params={
                "Bucket": 'XXX_BUCKET_NAME',
                "Key": 'XXX_OBJECT_KEY',
            },
        )
        r = requests.get(url=url, stream=True)
        r.raise_for_status()
        response = HttpResponse(r.raw, content_type='audio/mp3')
        response['Content-Disposition'] = 'inline; filename=music.mp3'
        return response
Run Code Online (Sandbox Code Playgroud)


Mal*_*Box 10

而不是代理,为什么不简单地重定向?

使用 www.myproject.com/downloads/1 上的 django 视图为 S3 存储 URL 提供 HTTP 重定向 - 可以生成限时的经过身份验证的 URL,例如,请参见此处https://docs.aws.amazon.com/AmazonS3 /latest/dev/ShareObjectPreSignedURL.html

然后客户端直接从 S3 下载文件,但内容仍然是安全的,访问必须通过您的 Django 应用程序

  • 我希望这里有其他答案。我需要同样的东西,除了我需要添加标题“内容处置:附件”。 (3认同)
  • @katylavallee 我能够使用重定向方法并通过将此参数添加到 `generate_presigned_url` 调用中来添加“Content-Disposition”标头: `'ResponseContentDisposition': 'attachment'` (2认同)