mar*_*595 1 python django amazon-s3 boto3
在我的项目中,我已经配置好并且可以正常使用S3 存储。现在,我正在尝试使用s3 direct配置直接上传到s3的功能。工作正常。用户能够上传图像并将其存储在S3中。当我在数据库中保存对图像的引用时,就会出现问题。
models.py
class FullResPicture(Audit):
docfile = models.ImageField()
picture = models.OneToOneField(Picture, primary_key=True)
Run Code Online (Sandbox Code Playgroud)
settings.py
...
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'),
}
...
Run Code Online (Sandbox Code Playgroud)
views.py
#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'])
Run Code Online (Sandbox Code Playgroud)
因此,如果我查看数据库,就会发现有些图像可以正常工作(仅使用django-storages上传的那些图像),其docfile值如下所示:
images/2015/08/11/image.jpg
Run Code Online (Sandbox Code Playgroud)
当应用程序尝试访问这些图像时,S3 boto能够正确获取图像。
但是之后,我直接从用户的浏览器上传了图像。对于这些,我存储了完整的URL,因此它们在数据库中看起来像这样:
https://s3-eu-west-1.amazonaws.com/bucket/uploads/imgs/Most-Famous-Felines-034.jpg
Run Code Online (Sandbox Code Playgroud)
当应用程序尝试访问它们时,我遇到了以下异常:
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.
Run Code Online (Sandbox Code Playgroud)
因此很明显,S3 boto不喜欢将文件引用作为完整的url。
出于故障排除的目的,我尝试对保存的值进行硬编码,因此它不保存完整的URL,而仅保存最后一部分,但是在尝试访问图像时出现了另一个异常:
IOError: File does not exist: uploads/imgs/Most-Famous-Felines-034.jpg
Run Code Online (Sandbox Code Playgroud)
有人知道这里出了什么问题吗?是否有人可以将直接上传到s3的工作示例存储在模型中?
谢谢。
这是我修复的方法,以防其他人使用。如果您已经使django- storages正常工作, 则可以使用此解决方案。django-s3direct从客户端上载图像,但是您无法使它们协同工作。
我要做的第一件事是确保django-storages和django-s3direct都配置为使用相同的存储桶。由于django-storages和django-s3direct已经分别工作,因此只需检查它们是否使用相同的存储桶即可。对于大多数用户,只需执行以下操作:
settings.py
...
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),
}
...
Run Code Online (Sandbox Code Playgroud)
请注意,我们使用AWS_STORAGE_BUCKET_NAME,应该为django-storages配置定义。
就我而言,情况稍复杂一些,因为我为不同的模型使用了不同的存储桶。
使用s3-direct时,一旦用户上传了图像并提交了表单,我们的视图将接收S3放置图像的URL。如果我们存储此URL,则当s3-storages尝试访问该图像时,它将不起作用,因此我们要做的就是仅存储文件的密钥。
文件的密钥是存储桶中图像的路径。例如,对于url https://s3-eu-west-1.amazonaws.com/bucket/uploads/imgs/Most-Famous-Felines-034.jpg,关键是uploads/imgs/Most-Famous-Felines-034.jpg,这就是我们需要在模型中存储的值。就我而言,我正在使用以下代码片段从网址中提取密钥:
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')
Run Code Online (Sandbox Code Playgroud)
一旦做出这些更改,它就可以无缝运行。我希望这可以帮助处于相同情况的任何人。
| 归档时间: |
|
| 查看次数: |
1422 次 |
| 最近记录: |