Django serwuje pliki do pobrania
Chcę, aby użytkownicy serwisu mogli pobierać pliki, których ścieżki są zasłonięte, więc nie można ich bezpośrednio pobrać.
Na przykład, chciałbym, aby adres URL był czymś takim, " http://example.com/download/?f=somefile.txt
A na serwerze wiem, że wszystkie pliki do pobrania znajdują się w folderze "/home/user/files/".
Czy istnieje sposób, aby Django podawało ten plik do pobrania, zamiast próbować znaleźć adres URL i wyświetlić go?
14 answers
Dla" najlepszego z obu światów " możesz połączyć rozwiązanie S. Lotta z modułem xsendfile : django generuje ścieżkę do pliku (lub samego pliku), ale rzeczywiste serwowanie plików jest obsługiwane przez Apache/Lighttpd. Po skonfigurowaniu pliku mod_xsendfile, integracja z widokiem zajmuje kilka linijek kodu:
from django.utils.encoding import smart_str
response = HttpResponse(mimetype='application/force-download') # mimetype is replaced by content_type for django 1.7
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
# It's usually a good idea to set the 'Content-Length' header too.
# You can also set any other required headers: Cache-Control, etc.
return response
Oczywiście będzie to działać tylko wtedy, gdy masz kontrolę nad serwerem lub Twoja firma hostingowa ma ustawiony plik mod_xsendfile w górę.
EDIT:
Typ MIME jest zastąpiony przez content_type dla django 1.7
response = HttpResponse(content_type='application/force-download'
EDIT:
Dla nginx
Sprawdź Ten, używa X-Accel-Redirect
zamiast apache
nagłówka X-Sendfile.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-15 12:19:55
"download" to po prostu zmiana nagłówka HTTP.
Potrzebujesz tylko jednej definicji URL dla "/download"
.
Słownik żądania GET
lub POST
będzie zawierał informacje "f=somefile.txt"
.
Funkcja widoku po prostu połączy ścieżkę bazową z wartością " f
", otworzy plik, utworzy i zwróci obiekt odpowiedzi. Powinno być mniej niż 12 linijek kodu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-20 23:20:15
S. Lott ma "dobre" / proste rozwiązanie, a elo80ka ma "najlepsze" / skuteczne rozwiązanie. Oto "lepsze" / środkowe rozwiązanie - brak konfiguracji serwera, ale bardziej wydajne dla dużych plików niż naiwna poprawka:
Http://djangosnippets.org/snippets/365/
Zasadniczo, Django nadal obsługuje serwowanie pliku, ale nie ładuje całości do pamięci na raz. Pozwala to serwerowi (powoli)obsługiwać duży plik bez zwiększania zużycia pamięci.
Znowu S. Lott ' s X-SendFile jest jeszcze lepszy dla większych plików. Ale jeśli nie możesz lub nie chcesz się tym przejmować, to środkowe rozwiązanie zapewni Ci lepszą wydajność bez kłopotów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-21 22:31:20
Dla bardzo prostego , ale nie wydajnego lub skalowalnego rozwiązania, możesz po prostu użyć wbudowanego widoku django serve
. Jest to doskonałe rozwiązanie do szybkich prototypów lub jednorazowej pracy, ale jak już wspomniano w tym pytaniu, powinieneś użyć czegoś takiego jak apache lub nginx w produkcji.
from django.views.static import serve
filepath = '/some/path/to/local/file.txt'
return serve(request, os.path.basename(filepath), os.path.dirname(filepath))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-18 22:54:28
Próbowałem rozwiązania @ Rocketmonkeys, ale pobrane pliki były przechowywane jako *.bin i podane losowe nazwy. To oczywiście nie w porządku. Dodanie kolejnej linijki z @elo80ka rozwiązało problem.
Oto kod, którego teraz używam:
from wsgiref.util import FileWrapper
from django.http import HttpResponse
filename = "/home/stackoverflow-addict/private-folder(not-porn)/image.jpg"
wrapper = FileWrapper(file(filename))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(filename)
response['Content-Length'] = os.path.getsize(filename)
return response
Możesz teraz przechowywać pliki w prywatnym katalogu (Nie wewnątrz /media ani /public_html) i udostępniać je przez django określonym użytkownikom lub w pewnych okolicznościach.
Mam nadzieję, że to pomoże.
podziękowania dla @elo80ka, @S. Lott i @Rocketmonkeys za odpowiedzi, mamy idealne rozwiązanie łączące je wszystkie =)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 23:41:14
Wspomniano powyżej, że metoda mod_xsendfile nie pozwala na użycie znaków innych niż ASCII w nazwach plików.
Z tego powodu mam dostępną łatkę dla mod_xsendfile, która pozwoli na wysłanie dowolnego pliku, o ile nazwa jest zakodowana url i dodatkowy nagłówek:
X-SendFile-Encoding: url
Jest również wysyłany.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-14 17:10:18
Wystarczy wspomnieć o obiekcie FileResponse dostępnym w Django 1.10
Edit: właśnie natknąłem się na moją własną odpowiedź podczas poszukiwania łatwego sposobu przesyłania strumieniowego plików przez Django, więc oto pełniejszy przykład(dla przyszłych mnie). Zakłada, że nazwa FileField to imported_file
views.py
from django.views.generic.detail import DetailView
from django.http import FileResponse
class BaseFileDownloadView(DetailView):
def get(self, request, *args, **kwargs):
filename=self.kwargs.get('filename', None)
if filename is None:
raise ValueError("Found empty filename")
some_file = self.model.objects.get(imported_file=filename)
response = FileResponse(some_file.imported_file, content_type="text/csv")
# https://docs.djangoproject.com/en/1.11/howto/outputting-csv/#streaming-large-csv-files
response['Content-Disposition'] = 'attachment; filename="%s"'%filename
return response
class SomeFileDownloadView(BaseFileDownloadView):
model = SomeModel
urls.py
...
url(r'^somefile/(?P<filename>[-\w_\\-\\.]+)$', views.SomeFileDownloadView.as_view(), name='somefile-download'),
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 15:18:53
Try: https://pypi.python.org/pypi/django-sendfile/
" abstrakcja do odciążania przesyłanych plików na serwer WWW (np. Apache z mod_xsendfile) po sprawdzeniu uprawnień przez Django itp."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-22 08:47:36
Powinieneś używać sendfile API podanych przez popularne serwery, takie jak apache
lub nginx
w produkcji. Wiele lat używałem sendfile api tych serwerów do ochrony plików. Następnie stworzyłem do tego celu prostą aplikację django opartą na oprogramowaniu middleware, odpowiednią zarówno do celów programistycznych, jak i produkcyjnych.Możesz uzyskać dostęp do kodu źródłowego tutaj .
UPDATE: w nowej wersji python
provider używa django FileResponse
jeśli jest dostępny, a także dodaje wsparcie dla wielu implementacji Serwerów od lighttp, caddy do hiawatha
Użycie
pip install django-fileprovider
- dodaj
fileprovider
aplikację doINSTALLED_APPS
ustawienia, - dodaj
fileprovider.middleware.FileProviderMiddleware
doMIDDLEWARE_CLASSES
ustawienia - Ustaw
FILEPROVIDER_NAME
nanginx
lubapache
w produkcji, domyślnie jest topython
w celu rozwoju.
W widokach classbased lub function Ustaw nagłówek odpowiedzi X-File
na bezwzględną ścieżkę do pliku. Na przykład,
def hello(request):
// code to check or protect the file from unauthorized access
response = HttpResponse()
response['X-File'] = '/absolute/path/to/file'
return response
django-fileprovider
w taki sposób, że Twój kod będzie potrzebował tylko minimum modyfikacja.
Konfiguracja Nginx
Aby chronić plik przed bezpośrednim dostępem, możesz ustawić konfigurację jako
location /files/ {
internal;
root /home/sideffect0/secret_files/;
}
Tutaj nginx
ustawia adres URL lokalizacji /files/
tylko dostęp wewnętrzny, jeśli używasz powyższej konfiguracji, możesz ustawić Plik X jako,
response['X-File'] = '/files/filename.extension'
Robiąc to z konfiguracją nginx, plik będzie chroniony i możesz kontrolować Plik z django views
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-13 16:08:29
Django zaleca używanie innego serwera do serwowania statycznych multimediów (inny serwer działający na tej samej maszynie jest w porządku.) Zalecają korzystanie z takich serwerów jak lighttp.
Jest to bardzo proste w konfiguracji. Jednak. if ' somefile.txt ' jest generowany na żądanie (treść jest dynamiczna) wtedy możesz chcieć, aby django ją obsłużyło.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-21 09:49:56
def qrcodesave(request):
import urllib2;
url ="http://chart.apis.google.com/chart?cht=qr&chs=300x300&chl=s&chld=H|0";
opener = urllib2.urlopen(url);
content_type = "application/octet-stream"
response = HttpResponse(opener.read(), content_type=content_type)
response["Content-Disposition"]= "attachment; filename=aktel.png"
return response
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 10:12:41
Kolejny projekt do obejrzenia: http://readthedocs.org/docs/django-private-files/en/latest/usage.html Wygląda obiecująco, Sam jeszcze tego nie testowałem.
Zasadniczo projekt streszcza konfigurację pliku mod_xsendfile i pozwala na wykonanie takich rzeczy jak:
from django.db import models
from django.contrib.auth.models import User
from private_files import PrivateFileField
def is_owner(request, instance):
return (not request.user.is_anonymous()) and request.user.is_authenticated and
instance.owner.pk = request.user.pk
class FileSubmission(models.Model):
description = models.CharField("description", max_length = 200)
owner = models.ForeignKey(User)
uploaded_file = PrivateFileField("file", upload_to = 'uploads', condition = is_owner)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-13 06:18:31
Miałem do czynienia z tym samym problemem więcej niż raz i tak zaimplementowany przy użyciu modułu xsendfile i dekoratorów widoku auth django-filelibrary. Zachęcamy do wykorzystania go jako inspiracji dla własnego rozwiązania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-01 22:07:51
Zapewnienie bezpiecznego dostępu do statycznego folderu html za pomocą https://github.com/johnsensible/django-sendfile: https://gist.github.com/iutinvg/9907731
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-01 04:35:39