Как смешать Django, Uploadify и S3Boto Storage Backend?

Фон

Я делаю довольно большие загрузки файлов на Django. Размер файла обычно составляет от 10 до 100 МБ.

Я на Heroku, и у меня истекло время ожидания запроса 30 секунд.

Начало

Чтобы обойти ограничение, рекомендуется Heroku загружать из браузера ПРЯМО на S3.

Amazon документирует это, показывая вам, как написать HTML-форму для выполнения загрузки.

Поскольку я использую Django, а не пишу HTML вручную, я использую https://github.com/sbc/django-uploadify-s3 ( пример). Это предоставляет мне SWF-объект, завернутый в JS, который выполняет фактическую загрузку.

Эта часть работает нормально! Ура!

Эта проблема

Проблема заключается в том, чтобы связать эти данные обратно с моей моделью Django. Прямо сейчас данные возвращаются в виде простой строки URL, указывающей на местоположение файла.

Однако ранее я использовал S3 Boto из django-хранилищ для управления всеми своими файлами как FileFieldsпри поддержке восхитительного S3BotoStorageFile,

Напомним, что S3 Boto отлично работает в изоляции, Uploadify прекрасно работает в изоляции, проблема в том, чтобы соединить их вместе.

Я понимаю, что единственный способ заселить FileField путем предоставления как имени файла, так и содержимого файла. Когда вы загружаете файлы из браузера в Django, это не проблема, поскольку Django хранит содержимое файла в буфере и может делать с ним все что угодно. Однако, когда я выполняю прямую загрузку на S3, как я, Django получает только имя файла и URL, а не двоичные данные, поэтому я не могу правильно заполнить FieldFile,

Молить о помощи

Кто-нибудь знает изящный способ использования FileField от S3Boto в сочетании с прямой загрузкой на S3?

Иначе, как лучше всего управлять файлом S3 только по его URL? В том числе установка срока действия, идентификатор ключа и т. Д.

Большое спасибо!

6 ответов

Используйте URLField.

У меня была похожая проблема, когда я хочу сохранить файл на s3 либо напрямую, используя FileField, либо у меня есть возможность для пользователя ввести URL-адрес напрямую. Поэтому, чтобы обойти это, я использовал 2 поля в моей модели, одно для FileField и одно для URLField. И в шаблоне я мог бы использовать 'или', чтобы увидеть, какой из них существует, и использовать его как {{ instance.filefield или instance.url }}.

Это не проверено, но вы должны быть в состоянии использовать:

from django.core.files.storage import default_storage
f = default_storage.open('name_you_expect_in_s3', 'r')
#f is an instance of S3BotoStorageFile, and can be assigned to a field
obj, created = YourObject.objects.get_or_create(**stuff_you_know)
obj.s3file_field = f
obj.save()

Я думаю, что это должно установить локальный указатель на s3 и сохранить его, не перезаписывая содержимое.

ETA: Вы должны сделать это только после завершения загрузки на S3, и вы знаете ключ в s3.

Оформить заказ на django-filetransfers. Похоже, это хорошо сочетается с Django-хранилищами.

Я никогда не использовал django, так что ymmv:), но почему бы просто не написать один байт для заполнения контента? Таким образом, вы все еще можете использовать FieldFile.

Я думаю, что написание реального SQL может быть самым простым решением здесь. В качестве альтернативы вы можете создать подкласс S3BotoStorage, переопределить метод _save и разрешить дополнительный kwarg filepath, который обходит все остальные элементы сохранения и просто возвращает cleaned_name.

Другие вопросы по тегам