10

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

http://www.myproject.com/downloads/1

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

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

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

谢谢。

4

2 回答 2

16

是的,您可以使用 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
于 2019-03-14T08:41:24.223 回答
10

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

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

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

于 2010-05-18T14:05:12.540 回答