Ответ 1
Используйте URLField.
Я делаю довольно большие загрузки файлов на Django. Размер файла обычно составляет 10 МБ-100 МБ.
Я нахожусь на Heroku, и я нажимаю на тайм-аут запроса 30 секунд.
Чтобы обойти предел, рекомендация Heroku должна загружаться из браузера DIRECTLY на S3.
Amazon документирует это, показывая вам, как написать HTML-форму для выполнения загрузки.
Поскольку я на Django, вместо того, чтобы писать HTML вручную, я использую django-uploadify-s3 (example). Это дает мне объект SWF, завернутый в JS, который выполняет фактическую загрузку.
Эта часть работает отлично! Ура!
Проблема заключается в привязке данных к моей модели Django разумным способом. Сейчас данные возвращаются как простая строка URL, указывая на расположение файла.
Однако ранее я использовал S3 Boto из django-хранилищ для управления всеми моими файлами как FileFields
, подкрепленные восхитительным S3BotoStorageFile
.
Чтобы повторить, S3 Boto отлично работает изолированно, Uploadify отлично работает изолированно, проблема заключается в том, чтобы объединить два.
Я понимаю, что единственный способ заполнить FileField
заключается в предоставлении имя_файла И файл содержание. Когда вы загружаете файлы из браузера в Django, это не проблема, поскольку Django имеет содержимое файла в буфере и может делать с ним все, что ему нравится. Тем не менее, при загрузке прямо на S3, как я, Django получает только имя файла и URL, а не двоичные данные, поэтому я не могу правильно заполнить FieldFile
.
Кто-нибудь знает грациозный способ использования S3Boto FileField в сочетании с прямой загрузкой S3?
Else, какой лучший способ управлять файлом S3 только на основе его URL-адреса? Включая истечение срока действия, идентификатор ключа и т.д.
Большое спасибо!
Используйте 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 пути к файлу, которая обойдена всем другим сохранением и просто возвращает очищенное имя.