django-storages и amazon s3 — подозрительная работа

Я использую django-хранилища с Amazon S3. Периодически вижу следующую ошибку:

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:.

Кто-нибудь знает, почему это появляется? Это не происходит все время. Я могу успешно сделать это в других случаях.


person Khandelwal    schedule 21.09.2012    source источник


Ответы (5)


_normalize_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())

И это сработало для простого ImageField django с этой базовой конфигурацией:

AWS_ACCESS_KEY_ID = 'TTTT'
AWS_SECRET_ACCESS_KEY = 'XXXX'
AWS_STORAGE_BUCKET_NAME = 'ZZZZ'
person danius    schedule 17.03.2015

Когда вы используете методы default_storage, обязательно используйте имя файла:

Правильный:

default_storage.delete(file.name)

Неправильно:

default_storage.delete(file.url)

Неправильно:

default_storage.delete(file)

Все три приведенных выше примера работают с локальными файлами, но при использовании s3 вы столкнетесь с этой ошибкой, если не используете имя файла.

person Arctelix    schedule 15.04.2013
comment
file.url обрабатывается иначе, чем file.name. Я также сделал это, но это больше похоже на взлом, чем на фактическое решение. Есть ли какие-либо источники, указывающие на то, что это действительно правильно, помимо того факта, что этот метод не вызывает исключения? - person Bryan; 05.02.2014
comment
Не то, чтобы я знаю. - person Arctelix; 07.02.2014

У меня еще не работало хранилище S3 над моим собственным проектом, но я только что столкнулся с этой ошибкой и, возможно, смогу указать вам правильное направление.

Если вы посмотрите на S3BotoStorage._clean_name(), это просто: return os.path.normpath(name).replace('\\', '/'). os.path.normpath() преобразует // в вашем URL-адресе в \\, а затем .replace() преобразует его в \. Затем S3BotoStorage._normalize_name() проверяет, является ли этот сломанный URL-адрес частью местоположения, которое он представляет, что, конечно же, не так. Вот где возникает ошибка SuspiciousOperation.

Таким образом, «имя» выглядит так, как будто это локальный путь, а не полный URL-адрес AWS. В моем случае непосредственной причиной была FILEBROWSER_DIRECTORY = MEDIA_URL + "uploads/" в settings.py, которую я пытался исправить, надеясь исправить другую ошибку, связанную с отсутствующей папкой для загрузки.

person toxotes    schedule 22.09.2012

Параметр

MEDIA_ROOT=''

исправил проблему для меня.

person manojlds    schedule 04.05.2013

Я исправил это, добавив SuspiciousOperation, кроме:

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