Асинхронная загрузка файлов в Amazon S3 с помощью Django - PullRequest
33 голосов
/ 22 марта 2009

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

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

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

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

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

Ответы [ 7 ]

24 голосов
/ 22 марта 2009

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

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

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

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

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

22 голосов
/ 11 мая 2009

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

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

18 голосов
/ 21 марта 2012

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

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

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

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

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

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

  3. Также можно настроить количество повторных попыток при сбое загрузки.

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

pip install django-queued-storage

добавить к INSTALLED_APPS:

INSTALLED_APPS += ('queued_storage',)

in 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)
6 голосов
/ 22 марта 2009

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

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

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

3 голосов
/ 16 апреля 2011

Вы можете напрямую загружать мультимедиа на сервер s3 без использования сервера веб-приложений.

См. Следующие ссылки:

Справочник по API Amazon: http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?UsingHTTPPOST.html

Реализация в django: https://github.com/sbc/django-uploadify-s3

0 голосов
/ 12 февраля 2013

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

Когда файл загружен с помощью формы, он становится доступным для просмотра в виде файла-подобного объекта UploadedFile. Вы можете получить его непосредственно из request.FILES или, лучше, сначала связать его с вашей формой, запустить 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

0 голосов
/ 05 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...