首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django和S3直接上传

Django和S3直接上传
EN

Stack Overflow用户
提问于 2015-10-18 20:05:28
回答 1查看 3K关注 0票数 1

在我的项目中,我已经配置好并正确工作了S3 储藏室。现在,我正在尝试使用s3配置直接上传到s3直接。它工作得几乎很好。用户可以上传图像并将其存储在S3中。当我在数据库中保存对图像的引用时,问题就会出现。

models.py

代码语言:javascript
复制
class FullResPicture(Audit):
    docfile = models.ImageField()
    picture = models.OneToOneField(Picture, primary_key=True)

settings.py

代码语言:javascript
复制
...
S3DIRECT_DESTINATIONS = {
    # Allow anybody to upload jpeg's and png's.
    'imgs': ('uploads/imgs', lambda u: u.is_authenticated(), ['image/jpeg', 'image/png'], 'public-read','bucket-name'),
}
...

views.py

代码语言:javascript
复制
#Doc file is the url to the image that the user uploaded directly to S3
#https://s3-eu-west-1.amazonaws.com/bucket/uploads/imgs/picture.jpeg
fullRes = FullResPicture(docfile = form_list[1].cleaned_data['docfile'])

因此,如果我查看我的DB,我已经得到了一些运行良好的图像(那些我仅使用django-storage上传的图像),其docfile值如下所示:

代码语言:javascript
复制
images/2015/08/11/image.jpg

当应用程序试图访问这些图像时,S3 boto能够正确地获取图像。

但是,我已经直接从用户的浏览器上传了图像。对于这些,我正在存储完整的url,所以它们在DB中如下所示:

代码语言:javascript
复制
https://s3-eu-west-1.amazonaws.com/bucket/uploads/imgs/Most-Famous-Felines-034.jpg

当应用程序试图访问它们时,我得到了以下异常:

代码语言:javascript
复制
File "/Users/mariopersonal/Documents/dev/venv/pictures/lib/python2.7/site-packages/django/db/models/fields/files.py", line 49, in _get_file
    self._file = self.storage.open(self.name, 'rb')
  File "/Users/mariopersonal/Documents/dev/venv/pictures/lib/python2.7/site-packages/django/core/files/storage.py", line 35, in open
    return self._open(name, mode)
  File "/Users/mariopersonal/Documents/dev/venv/pictures/lib/python2.7/site-packages/storages/backends/s3boto.py", line 363, in _open
    name = self._normalize_name(self._clean_name(name))
  File "/Users/mariopersonal/Documents/dev/venv/pictures/lib/python2.7/site-packages/storages/backends/s3boto.py", line 341, in _normalize_name
    name)
SuspiciousOperation: Attempted access to 'https:/s3-eu-west-1.amazonaws.com/bucket/uploads/imgs/Most-Famous-Felines-034.jpg' denied.

因此,显然,S3 boto不喜欢文件引用作为完整的url。

为了排除故障,我尝试对保存的值进行硬编码,所以它只保存最后一部分,而不是完整的url,但是当它试图访问图像时,我得到了另一个异常:

代码语言:javascript
复制
IOError: File does not exist: uploads/imgs/Most-Famous-Felines-034.jpg

有人知道这里出了什么问题吗?有没有人有直接上传到s3的工作示例,将对上传文件的引用存储在模型中?

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2015-10-19 16:01:14

这就是我修的方法,以防它对别人有帮助。这个解决方案适用于,如果您已经让django-仓库正常工作,那么django-s3直接会从客户端上传图像,但是您不能让它们一起工作。

用同样的水桶

我做的第一件事就是确保django-存储和django-s3direct都配置为使用相同的桶。由于已经有django-存储和django-s3直接单独工作,所以只需检查两者是否使用相同的桶。对于大多数用户来说,只需要这样做:

settings.py

代码语言:javascript
复制
...
S3DIRECT_DESTINATIONS = {
    # Allow anybody to upload jpeg's and png's.
    'imgs': ('uploads/imgs', lambda u: u.is_authenticated(), ['image/jpeg', 'image/png'], 'public-read', AWS_STORAGE_BUCKET_NAME),
}
...

请注意,我们使用的是AWS_STORAGE_BUCKET_NAME,应该为django-存储配置定义它。

在我的例子中,要复杂一点,因为我使用不同的桶为不同的模型。

只存储密钥

当使用S3直接时,一旦用户上传了图像并提交了表单,我们的视图将收到S3放置图像的url。如果我们存储这个url,当s3-存储试图访问图像时,它将不能工作,所以我们要做的是只存储文件的密钥。

文件的关键是桶内图像的路径。例如,对于url https://s3-eu-west-1.amazonaws.com/bucket/uploads/imgs/Most-Famous-Felines-034.jpguploads/imgs/Most-Famous-Felines-034.jpg,因此这是我们需要存储在模型上的值。在我的例子中,我使用这个片段从url中提取密钥:

代码语言:javascript
复制
def key_from_url(url, bucket):
    try:
        indexOf = url.index(bucket)
        return url[indexOf:]
    except:
        raise ValueError('The url provided does not match the bucket name')

一旦我做了这些改变,它就无缝地工作了。我希望这对处于同样情况的任何人都有帮助。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33202644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档