Загрузка асинхронного файла в Amazon S3 с помощью Django

Я использую этот механизм хранения файлов для хранения файлов на Amazon S3 при их загрузке:

http://code.welldev.org/django-storages/wiki/Home

Загрузка занимает довольно много времени, потому что сначала файл должен быть загружен с клиента на веб-сервер, а затем веб-сервер на Amazon S3, прежде чем ответ будет возвращен клиенту.

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

Спасибо за ваш совет!

Ответ 1

Я использовал другой подход к этой проблеме.

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

У меня есть команда управления в моем приложении, которая загружает все локально сохраненные файлы в s3 и обновляет модели.

Итак, когда запрос приходит к файлу, я проверяю, использует ли объект модели поле хранения s3, если это так, я отправляю перенаправление на правильный URL-адрес на s3, если я не отправляю перенаправление, так что nginx может обслуживать файл с диска.

Эта команда управления может быть вызвана любым событием cronjob или любым другим.

Ответ 2

Возможно, ваши пользователи загружают файлы непосредственно на S3 из своего браузера, используя специальную форму (с зашифрованным политическим документом в скрытом поле). После завершения загрузки они будут перенаправлены обратно в ваше приложение.

Дополнительная информация здесь: http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1434

Ответ 3

Для этого есть приложение: -)

https://github.com/jezdez/django-queued-storage

Он делает именно то, что вам нужно - и многое другое, потому что вы можете установить любое "локальное" хранилище и любое хранилище "remote". Это приложение будет хранить ваш файл в быстром "локальном" хранилище (например, в хранилище MogileFS), а затем с помощью Celery (django-celery), будет попробуйте асинхронную загрузку в хранилище "remote".

Несколько замечаний:

  • Трудность заключается в том, что вы можете настроить его для копирования, загрузки или загрузки и удаления стратегии, которая удалит локальный файл после его загрузки.

  • Вторая сложная вещь - она ​​будет обслуживать файл из "локального" хранилища, пока он не будет загружен.

  • Он также может быть настроен на то, чтобы количество попыток при загрузке было неудачным.

Установка и использование также очень просты и понятны:

pip install django-queued-storage

добавить к INSTALLED_APPS:

INSTALLED_APPS += ('queued_storage',)

в models.py:

from queued_storage.backends import QueuedStorage
queued_s3storage = QueuedStorage(
    'django.core.files.storage.FileSystemStorage',
    'storages.backends.s3boto.S3BotoStorage', task='queued_storage.tasks.TransferAndDelete')

class MyModel(models.Model):
    my_file = models.FileField(upload_to='files', storage=queued_s3storage)

Ответ 4

Вы можете отделить процесс:

  • пользователь выбирает файл для загрузки и отправляет его на ваш сервер. После этого он видит страницу "Спасибо, что вы загрузили файл foofile.txt, теперь он хранится в нашем хранилище"
  • Когда пользователи загружают файл, он хранит временный каталог на вашем сервере и, при необходимости, некоторые метаданные хранятся в вашей базе данных.
  • Фоновый процесс на вашем сервере затем загружает файл на S3. Это было бы возможно только в том случае, если у вас есть полный доступ к вашему серверу, чтобы вы могли создать для этого какой-то "деамон" (или просто использовать cronjob). *
  • Отображаемая страница выполняет асинхронный опрос и отображает для пользователя какой-то индикатор выполнения (или просто "пожалуйста, подождите" "Сообщение". Это будет необходимо, только если пользователь должен "использовать" (поместить его в сообщение или что-то в этом роде) сразу после загрузки.

[*: Если у вас есть только общий хостинг, вы можете создать какое-то решение, которое использует скрытый iframe в браузере пользователей, чтобы запустить script, который затем загружает файл на S3]

Ответ 6

Как некоторые из ответов здесь предлагают загрузить непосредственно на S3, здесь Django S3 Mixin с использованием plupload: https://github.com/burgalon/plupload-s3mixin

Ответ 7

Я столкнулся с той же проблемой с загруженными изображениями. Вы не можете передавать файлы работнику сельдерей, потому что сельдерей должен уметь аргументировать задачу. Мое решение состояло в том, чтобы деконструировать данные изображения в строку и получить всю другую информацию из файла, передав эти данные и информацию в задачу, где я восстановил изображение. После этого вы можете сохранить его, который отправит его на ваш бэкэнд хранилища (например, S3). Если вы хотите связать образ с моделью, просто пройдите по идентификатору экземпляра задачи и извлеките его там, привяжите образ к экземпляру и сохраните экземпляр.

Когда файл загружен через форму, он доступен в вашем представлении как файл, подобный файлу UploadedFile. Вы можете получить его непосредственно из запроса. ФАЙЛЫ, или лучше сначала привязать его к вашей форме, запустите is_valid и извлеките файл-подобный объект из form.cleaned_data. В этот момент, по крайней мере, вы знаете, что это тот файл, который вы хотите. После этого вы можете получить данные, используя read(), и получить другую информацию, используя другие методы/атрибуты. См. https://docs.djangoproject.com/en/1.4/topics/http/file-uploads/

Я фактически закончил писать и распространять небольшой пакет, чтобы сохранить изображение асинхронно. Взгляните на https://github.com/gterzian/django_async Правильно, только для изображений, и вы можете разветкить его и добавить функциональные возможности для своей ситуации. Я использую его с https://github.com/duointeractive/django-athumb и S3