Я хочу, чтобы пользователи на сайте могли загружать файлы, пути которых скрыты, поэтому их нельзя напрямую загрузить.
Например, я бы хотел, чтобы URL был примерно таким: http://example.com/download/?f=somefile.txt
И на сервере я знаю, что все загружаемые файлы находятся в папке /home/user/files/
.
Есть ли способ заставить Django обслуживать этот файл для загрузки, в отличие от попыток найти URL и View для его отображения?
Ответы:
Для «лучшего из двух миров» вы можете объединить решение S.Lott с модулем xsendfile : django генерирует путь к файлу (или сам файл), но фактическая обработка файла обрабатывается Apache / Lighttpd. После настройки mod_xsendfile интеграция с вашим представлением занимает несколько строк кода:
Конечно, это будет работать, только если у вас есть контроль над вашим сервером, или в вашей хостинговой компании уже установлен mod_xsendfile.
РЕДАКТИРОВАТЬ:
EDIT: Для
nginx
проверки этого , он используетX-Accel-Redirect
вместоapache
заголовка X-SendFile.источник
smart_str
они не работают должным образом, так как X-Sendfile модуля apache не может декодировать строку, закодированную в smart_str. Так, например, файл «Örinää.mp3» не может быть предоставлен. И если не указывать smart_str, Django сам выдает ошибку кодирования ascii, потому что все заголовки перед отправкой кодируются в формат ascii. Единственный способ, который я знаю, чтобы обойти эту проблему - это сократить имена файлов X-sendfile до тех, которые состоят только из ascii.«Загрузка» - это просто изменение заголовка HTTP.
См. Http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment, чтобы узнать, как ответить загрузкой. ,
Вам нужно только одно определение URL для
"/download"
.Запрос
GET
илиPOST
словарь будут иметь"f=somefile.txt"
информацию.Ваша функция просмотра просто объединит базовый путь со значением "
f
", откроет файл, создаст и вернет объект ответа. Должно быть меньше 12 строк кода.источник
filepath = filepath.replace('..', '').replace('/', '')
Для очень простого, но неэффективного или масштабируемого решения вы можете просто использовать встроенное представление django
serve
. Это отлично подходит для быстрых прототипов или одноразовой работы, но, как уже упоминалось в этом вопросе, вы должны использовать что-то вроде apache или nginx в производстве.источник
S.Lott предлагает «хорошее» / простое решение, а elo80ka предлагает «лучшее» / эффективное решение. Вот «лучшее» / среднее решение - без настройки сервера, но более эффективное для больших файлов, чем наивное исправление:
http://djangosnippets.org/snippets/365/
По сути, Django по-прежнему обрабатывает файл, но не загружает все это в память сразу. Это позволяет вашему серверу (медленно) обслуживать большой файл без увеличения использования памяти.
Опять же, S.Lott X-SendFile все еще лучше для больших файлов. Но если вы не можете или не хотите беспокоиться об этом, тогда это промежуточное решение повысит вашу эффективность без хлопот.
источник
django.core.servers.httpbase
недокументированном закрытом модуле, который имеет большой предупреждающий знак в верхней части кода « НЕ ИСПОЛЬЗОВАТЬ ДЛЯ ПРОИЗВОДСТВА ИСПОЛЬЗОВАНИЯ !!! », который находится в файле с момента его создания . В любом случае,FileWrapper
функциональность этого фрагмента была удалена в django 1.9.Пробовал решение @Rocketmonkeys, но загруженные файлы хранились как * .bin и имели случайные имена. Это не хорошо, конечно. Добавление еще одной строки из @ elo80ka решило проблему.
Вот код, который я использую сейчас:
Теперь вы можете хранить файлы в личном каталоге (не внутри / media или / public_html) и предоставлять их через django определенным пользователям или при определенных обстоятельствах.
Надеюсь, поможет.
Спасибо @ elo80ka, @ S.Lott и @Rocketmonkeys за ответы, они получили идеальное решение, объединив все из них =)
источник
filename="%s"
в заголовке Content-Disposition, чтобы избежать проблем с пробелами в именах файлов. Ссылки: Имена файлов с пробелами усечены на загрузки , Как кодировать параметр имя файла заголовка Content-Disposition в HTTP?FileWrapper(open(path.abspath(file_name), 'rb'))
FileWrapper
удалено с Django 1.9from wsgiref.util import FileWrapper
Просто упомяну объект FileResponse, доступный в Django 1.10
Изменить: Просто столкнулся с моим собственным ответом при поиске простого способа для потоковой передачи файлов через Django, так что вот более полный пример (для будущего меня). Предполагается, что имя FileField
imported_file
views.py
urls.py
источник
Выше было упомянуто, что метод mod_xsendfile не допускает использование символов не-ASCII в именах файлов.
По этой причине у меня есть патч для mod_xsendfile, который позволит отправлять любой файл, если имя закодировано в URL, и дополнительный заголовок:
Также отправлено.
http://ben.timby.com/?p=149
источник
Попробуйте: https://pypi.python.org/pypi/django-sendfile/
«Абстракция для выгрузки файлов на веб-сервер (например, Apache с mod_xsendfile) после проверки прав доступа Django и т. Д.»
источник
Вы должны использовать apis sendfile, предоставляемые популярными серверами, такими как
apache
илиnginx
в производстве. Много лет я использовал sendfile api этих серверов для защиты файлов. Затем для этой цели было создано простое приложение django на основе промежуточного программного обеспечения, подходящее как для разработки, так и для производства. Вы можете получить доступ к исходному коду здесь .ОБНОВЛЕНИЕ: в новой версии
python
провайдер использует django,FileResponse
если доступно, а также добавляет поддержку многих реализаций сервера от lighthttp, caddy до hiawathaиспользование
fileprovider
приложение вINSTALLED_APPS
настройки,fileprovider.middleware.FileProviderMiddleware
вMIDDLEWARE_CLASSES
настройкиFILEPROVIDER_NAME
настройки наnginx
илиapache
в производстве, по умолчанию этоpython
для целей разработки.в ваших представлениях классов или функций установите
X-File
значение заголовка ответа в виде абсолютного пути к файлу. Например,django-fileprovider
таким образом, что ваш код будет нуждаться только в минимальной модификации.Конфигурация Nginx
Чтобы защитить файл от прямого доступа, вы можете установить конфигурацию как
Здесь
nginx
задает адрес URL/files/
только для внутреннего доступа, если вы используете вышеуказанную конфигурацию, вы можете установить X-File как,Делая это с конфигурацией nginx, файл будет защищен, а также вы можете управлять файлом из django
views
источник
Django рекомендует использовать другой сервер для обслуживания статического носителя (другой сервер, работающий на той же машине, подойдет ). Они рекомендуют использовать такие серверы как lighttp .
Это очень просто настроить. Тем не мение. если 'somefile.txt' генерируется по запросу (контент динамический), вы можете захотеть, чтобы django его обслуживал.
Django Docs - Статические файлы
источник
источник
Еще один проект, на который можно посмотреть: http://readthedocs.org/docs/django-private-files/en/latest/usage.html Выглядит многообещающе, сам пока не тестировал его, хотя.
По сути, проект абстрагирует конфигурацию mod_xsendfile и позволяет вам делать такие вещи, как:
источник
django-private-files
...Я сталкивался с той же проблемой более одного раза и реализовал ее с помощью модуля xsendfile и декораторов представления auth django-filelibrary . Не стесняйтесь использовать его как вдохновение для вашего собственного решения.
https://github.com/danielsokolowski/django-filelibrary
источник
Предоставление защищенного доступа к статической папке html с использованием https://github.com/johnsensible/django-sendfile : https://gist.github.com/iutinvg/9907731
источник
Я сделал проект по этому вопросу. Вы можете посмотреть на мой репозиторий github:
https://github.com/nishant-boro/django-rest-framework-download-expert
Этот модуль предоставляет простой способ обслуживания файлов для загрузки в django rest framework с использованием модуля Apache Xsendfile. Он также имеет дополнительную функцию загрузки загрузок только пользователям, принадлежащим к определенной группе.
источник