【问题标题】:Download files from Amazon S3 with Django使用 Django 从 Amazon S3 下载文件
【发布时间】:2012-10-10 03:01:11
【问题描述】:

我有一个 Django 应用程序,它允许用户下载他们购买的 MP3 文件,这些 MP3 文件托管在 Amazon S3 中。当用户单击“下载”按钮而不允许他们查看原始链接(到亚马逊)时,我如何强制下载? 我有一个下载文件的视图,但文件已损坏。 这是它的样子:

def download(request):
    filename = 'https://s3-eu-west-1.amazonaws.com/skempi/Ihsahn/04-emancipation-qtxmp3.mp3'
    response = HttpResponse(mimetype='application/force-download')
    response['Content-Disposition']='attachment;filename="%s"'%filename
    response["X-Sendfile"] = filename
    return response

【问题讨论】:

标签: django amazon-s3


【解决方案1】:

如果您不希望文件可下载,请将 ACL 设置为私有(只能通过您的帐户访问)。如果您向他们提供签名 URL,您的用户仍然可以下载文件。当您签署 URL 时,您会生成带有过期时间的令牌。您可以将其设置为合理的 10 分钟。使用Amazon Web Services interface for Python — Boto

import boto
conn = boto.connect_s3('<aws access key>', '<aws secret key>')
bucket = conn.get_bucket('your_bucket')
s3_file_path = bucket.get_key('path/to/file')
url = s3_file_path.generate_url(expires_in=600) # expiry time is in seconds

return HttpResponseRedirect(url)

请注意,这是安全的,因为令牌仅对一种请求方法(默认为 GET)有效,并且仅对一个文件有效。因此,没有人重复使用令牌的风险,例如下载其他文件或操纵给定的文件。

【讨论】:

  • 我试过了,但在bucket = conn.get_bucket('my_bucket') 之后我收到S3ResponseError: S3ResponseError: 403 Forbidden 错误,并且在消息标签中有The difference between the request time and the current time is too large.
  • @Mohamed:您本地机器上的时间不同步。您应该使用例如NTP 设置自动同步。
  • 当我尝试使用 AS3 从 Django 管理面板上传文件时遇到同样的错误,您认为问题仍然存在于时间不同步
  • 非常感谢!我已经为此苦苦挣扎了几个小时了。
  • @MohamedTurki:你的机器上的时区设置可能有问题。
【解决方案2】:

我无法轻易找到指定如何执行此操作的任何地方,并在我搜索时一次又一次地回到这个问题。所以

使用 django-storages 使用 boto 后端,这样做的方法类似于

filepath = settings.MEDIA_DIRECTORY + file.name
response_headers = {
    'response-content-type': 'application/force-download',
    'response-content-disposition':'attachment;filename="%s"'%file.name
    }
url = s3.generate_url(60, 'GET',
                bucket=settings.AWS_STORAGE_BUCKET_NAME,
                key=filepath,
                response_headers=response_headers,
                force_http=True)
return http.HttpResponseRedirect(url)

【讨论】:

  • 我发现这目前是 django-storages 内置的。按照你上面的例子,这可以实现为:url = storage.url(filepath, headers=response_headers)
【解决方案3】:

上面的答案已经过时,因为它们使用 boto 而不是 boto3。这就是使用 boto3 的方式:

import boto3

client = boto3.client('s3', aws_access_key_id = config('AWS_ACCESS_KEY_ID'), /
aws_secret_access_key = config('AWS_SECRET_ACCESS_KEY'))
bucket_name = config('AWS_STORAGE_BUCKET_NAME')
file_name = settings.AWS_MEDIA_LOCATION + '/' + 'file-name'

url = client.generate_presigned_url(
                                    'get_object', 
                                    Params = { 
                                                'Bucket': bucket_name, 
                                                'Key': file_name, }, 
                                    ExpiresIn = 600, )
return HttpResponseRedirect(url)

【讨论】:

    猜你喜欢
    • 2013-05-08
    • 2012-08-29
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2014-11-28
    • 1970-01-01
    相关资源
    最近更新 更多