django存储和amazon s3-可疑操作

django存储和amazon s3-可疑操作,django,amazon-s3,python-django-storages,Django,Amazon S3,Python Django Storages,我在AmazonS3上使用django存储。我偶尔会看到以下错误: name = self._normalize_name(self._clean_name(name))\n\n File \"/app/.heroku/venv/lib/python2.7/site-packages/storages/backends/s3boto.py\", line 237, in _normalize_name\n name)\n\nSuspiciousOperation: Attempted a

我在AmazonS3上使用django存储。我偶尔会看到以下错误:

name = self._normalize_name(self._clean_name(name))\n\n  File \"/app/.heroku/venv/lib/python2.7/site-packages/storages/backends/s3boto.py\", line 237, in _normalize_name\n    name)\n\nSuspiciousOperation: Attempted access to 'https:/plantvillage.s3.amazonaws.com/avatar/hans9_avatar.jpg'
请注意
https:
之后的单个
/


有人知道为什么会出现这种情况吗?这种情况并非总是发生。我可以在其他情况下成功地做到这一点

我还没有让S3存储在我自己的项目上运行,但我确实遇到了这个错误,也许可以为您指出正确的方向

如果您查看s3botostrage.\u clean\u name(),它只是:
返回os.path.normpath(name).replace('\\','/')
。 os.path.normpath()将URL中的//转换为\,然后.replace()将其转换为\。然后,s3botostrage.\u normalize\u name()检查以确保此断开的URL是它所表示位置的一部分,当然不是。这就是引起可疑操作错误的地方


所以“name”看起来像是一个本地路径,而不是整个AWS URL。在我的例子中,直接原因是settings.py中的
FILEBROWSER\u DIRECTORY=MEDIA\u URL+“uploads/”
,我曾试图修复关于丢失上载文件夹的不同错误。

使用默认存储方法时,请确保使用文件名:

正确:

default_storage.delete(file.name)
错:

default_storage.delete(file.url)
default_storage.delete(file)
错:

default_storage.delete(file.url)
default_storage.delete(file)
以上三个示例都适用于本地文件,但使用s3时,除非使用file.name,否则会遇到此错误。

设置

MEDIA_ROOT=''

为我修复了这个问题。

\u normalize\u name对Django的URL内容做了很多花哨的、基本上不必要的处理。在我的例子中,我只是覆盖了S3BotoStorage,如下所示:

class S3CustomStorage(S3BotoStorage):
def _normalize_name(self, name):
    """
    Get rid of this crap: http://stackoverflow.com/questions/12535123/django-storages-and-amazon-s3-suspiciousoperation
    """
    return name
然后在存储属性中使用它:

ImageField(storage=S3CustomStorage())
它适用于django simple ImageField的基本配置:

AWS_ACCESS_KEY_ID = 'TTTT'
AWS_SECRET_ACCESS_KEY = 'XXXX'
AWS_STORAGE_BUCKET_NAME = 'ZZZZ'

我修复了此问题,在上添加了可疑操作,除了:

class S3CustomStorage(S3BotoStorage):
    def _normalize_name(self, name):
        try:
            return safe_join(self.location, name)
        except (SuspiciousOperation, ValueError):
            return ""

file.url
的处理方式与
file.name
不同。我也这样做过,但它看起来更像是一个黑客而不是一个实际的解决方案。除了这个方法没有引起异常之外,还有什么来源表明这确实是正确的吗?我不知道。