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

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

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

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

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

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


person Community    schedule 22.03.2009    source источник


Ответы (7)


Я применил другой подход к этой проблеме.

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

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

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

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

person Vasil    schedule 22.03.2009

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

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

person Simon Willison    schedule 11.05.2009
comment
Чудесно! Это - решение для прямой загрузки S3. Спасибо, Саймон! - person Yuval Adam; 30.03.2011
comment
Фактически, вы не можете проверить запрос на загрузку и какие-либо прикрепленные данные, что вызывает недостаток безопасности. - person Ilya Ilin; 06.04.2016

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

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)
person thedk    schedule 21.03.2012
comment
как мне заставить его заменить исходный файл, я пытаюсь повторно загрузить новый файл ?? прямо сейчас его создание name_1, name_2 и т. д. - person psychok7; 15.07.2014

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

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

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

person Martin Thurau    schedule 22.03.2009

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

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

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

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

person digitalPBK    schedule 16.04.2011

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

person Alon Burg    schedule 05.09.2011

Я столкнулся с той же проблемой с загруженными изображениями. Вы не можете передавать файлы работнику 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

person gterzian    schedule 12.02.2013