Je souhaite que les utilisateurs du site puissent télécharger des fichiers dont les chemins sont masqués afin qu'ils ne puissent pas être téléchargés directement.
Par exemple, j'aimerais que l'URL soit quelque chose comme ceci: http://example.com/download/?f=somefile.txt
Et sur le serveur, je sais que tous les fichiers téléchargeables résident dans le dossier /home/user/files/
.
Existe-t-il un moyen de faire en sorte que Django serve ce fichier à télécharger au lieu d'essayer de trouver une URL et de la visualiser pour l'afficher?
Réponses:
Pour le "meilleur des deux mondes", vous pouvez combiner la solution de S.Lott avec le module xsendfile : django génère le chemin vers le fichier (ou le fichier lui-même), mais le service de fichier réel est géré par Apache / Lighttpd. Une fois que vous avez configuré mod_xsendfile, l'intégration à votre vue prend quelques lignes de code:
Bien sûr, cela ne fonctionnera que si vous avez le contrôle sur votre serveur, ou si votre hébergeur a déjà configuré mod_xsendfile.
ÉDITER:
EDIT: Pour
nginx
vérifier cela , il utilise à laX-Accel-Redirect
place de l'enapache
-tête X-Sendfile.la source
smart_str
ne fonctionne pas comme prévu car le module apache X-Sendfile ne peut pas décoder la chaîne codée smart_str. Ainsi, par exemple, le fichier "Örinää.mp3" ne peut pas être servi. Et si l'on omet le smart_str, le Django lui-même génère une erreur de codage ascii car tous les en- têtes sont codés au format ascii avant l'envoi. La seule façon que je connaisse pour contourner ce problème est de réduire les noms de fichiers X-sendfile à ceux qui ne comprennent que ascii.Un "téléchargement" est simplement un changement d'en-tête HTTP.
Voir http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment pour savoir comment répondre avec un téléchargement .
Vous n'avez besoin que d'une définition d'URL pour
"/download"
.La demande
GET
ou lePOST
dictionnaire contiendra les"f=somefile.txt"
informations.Votre fonction d'affichage fusionnera simplement le chemin de base avec la
f
valeur " ", ouvrira le fichier, créera et renverra un objet de réponse. Il doit contenir moins de 12 lignes de code.la source
filepath = filepath.replace('..', '').replace('/', '')
Pour une solution très simple mais pas efficace ou évolutive , vous pouvez simplement utiliser la
serve
vue django intégrée . C'est excellent pour les prototypes rapides ou les travaux ponctuels, mais comme cela a été mentionné tout au long de cette question, vous devez utiliser quelque chose comme apache ou nginx en production.la source
S.Lott a la "bonne" / solution simple, et elo80ka a la "meilleure" / solution efficace. Voici une "meilleure" solution / intermédiaire - pas de configuration de serveur, mais plus efficace pour les gros fichiers que le correctif naïf:
http://djangosnippets.org/snippets/365/
Fondamentalement, Django gère toujours le service du fichier mais ne charge pas le tout en mémoire à la fois. Cela permet à votre serveur de servir (lentement) un gros fichier sans augmenter l'utilisation de la mémoire.
Encore une fois, le fichier X-SendFile de S.Lott est encore meilleur pour les fichiers plus volumineux. Mais si vous ne pouvez pas ou ne voulez pas vous en préoccuper, cette solution intermédiaire vous permettra de gagner en efficacité sans les tracas.
la source
django.core.servers.httpbase
module privé non documenté, qui a un grand panneau d'avertissement en haut du code " NE PAS UTILISER POUR L'UTILISATION DE LA PRODUCTION !!! ", qui se trouve dans le fichier depuis sa création . Dans tous les cas, laFileWrapper
fonctionnalité sur laquelle repose cet extrait a été supprimée dans django 1.9.J'ai essayé la solution @Rocketmonkeys mais les fichiers téléchargés étaient stockés sous * .bin et donnaient des noms aléatoires. Ce n'est pas très bien sûr. L'ajout d'une autre ligne à partir de @ elo80ka a résolu le problème.
Voici le code que j'utilise maintenant:
Vous pouvez désormais stocker des fichiers dans un répertoire privé (pas à l'intérieur de / media ni / public_html) et les exposer via django à certains utilisateurs ou dans certaines circonstances.
J'espère que ça aide.
Merci à @ elo80ka, @ S.Lott et @Rocketmonkeys pour les réponses, a obtenu la solution parfaite en les combinant tous =)
la source
filename="%s"
dans l'en-tête Content-Disposition, pour éviter les problèmes avec les espaces dans les noms de fichiers. Références: Les noms de fichiers avec des espaces sont tronqués lors du téléchargement , comment coder le paramètre de nom de fichier de l'en-tête Content-Disposition en HTTP?FileWrapper(open(path.abspath(file_name), 'rb'))
FileWrapper
a été supprimé depuis Django 1.9from wsgiref.util import FileWrapper
Il suffit de mentionner l' objet FileResponse disponible dans Django 1.10
Edit: Je suis juste tombé sur ma propre réponse lors de la recherche d'un moyen simple de diffuser des fichiers via Django, voici donc un exemple plus complet (pour moi à l'avenir). Il suppose que le nom FileField est
imported_file
views.py
urls.py
la source
Il a été mentionné ci-dessus que la méthode mod_xsendfile ne permet pas les caractères non ASCII dans les noms de fichiers.
Pour cette raison, j'ai un correctif disponible pour mod_xsendfile qui permettra d'envoyer n'importe quel fichier, tant que le nom est encodé en url, et l'en-tête supplémentaire:
Est également envoyé.
http://ben.timby.com/?p=149
la source
Essayez: https://pypi.python.org/pypi/django-sendfile/
"Abstraction pour décharger les téléchargements de fichiers sur le serveur Web (par exemple Apache avec mod_xsendfile) une fois que Django a vérifié les autorisations, etc."
la source
Vous devez utiliser des API sendfile fournies par des serveurs populaires comme
apache
ounginx
en production. De nombreuses années, j'utilisais l'API Sendfile de ces serveurs pour protéger les fichiers. Vous avez ensuite créé une application Django basée sur un middleware simple à cet effet, adaptée à la fois au développement et à la production.Vous pouvez accéder au code source ici .MISE À JOUR: dans la nouvelle version, le
python
fournisseur utilise djangoFileResponse
s'il est disponible et ajoute également la prise en charge de nombreuses implémentations de serveur de lighthttp, caddy à hiawathaUsage
fileprovider
application auxINSTALLED_APPS
paramètres,fileprovider.middleware.FileProviderMiddleware
auxMIDDLEWARE_CLASSES
paramètresFILEPROVIDER_NAME
paramètres surnginx
ouapache
en production, par défaut, c'estpython
à des fins de développement.dans vos vues de classe ou de fonction, définissez la
X-File
valeur de l'en- tête de réponse sur le chemin absolu du fichier. Par exemple,django-fileprovider
mis en œuvre de manière à ce que votre code ne nécessite qu'une modification minimale.Configuration de Nginx
Pour protéger le fichier d'un accès direct, vous pouvez définir la configuration comme
Définit ici
nginx
une URL d'emplacement/files/
uniquement pour l'accès interne, si vous utilisez la configuration ci-dessus, vous pouvez définir X-File comme,En faisant cela avec la configuration nginx, le fichier sera protégé et vous pouvez également contrôler le fichier à partir de django
views
la source
Django vous recommande d'utiliser un autre serveur pour servir des supports statiques (un autre serveur fonctionnant sur la même machine est très bien.) Ils recommandent l'utilisation de tels serveurs comme lighttp .
C'est très simple à mettre en place. Toutefois. si 'somefile.txt' est généré sur demande (le contenu est dynamique) alors vous voudrez peut-être que django le serve.
Django Docs - Fichiers statiques
la source
la source
Un autre projet à voir: http://readthedocs.org/docs/django-private-files/en/latest/usage.html Il semble prometteur, je ne l'ai pas encore testé moi-même.
Fondamentalement, le projet résume la configuration mod_xsendfile et vous permet de faire des choses comme:
la source
django-private-files
...J'ai rencontré le même problème plus d'une fois et donc implémenté en utilisant le module xsendfile et les décorateurs de vue auth de la django-filelibrary . N'hésitez pas à l'utiliser comme source d'inspiration pour votre propre solution.
https://github.com/danielsokolowski/django-filelibrary
la source
Fournir un accès protégé au dossier html statique à l'aide de https://github.com/johnsensible/django-sendfile : https://gist.github.com/iutinvg/9907731
la source
J'ai fait un projet là-dessus. Vous pouvez regarder mon repo github:
https://github.com/nishant-boro/django-rest-framework-download-expert
Ce module fournit un moyen simple de servir des fichiers à télécharger dans le framework de repos django en utilisant le module Apache Xsendfile. Il a également une fonctionnalité supplémentaire de servir les téléchargements uniquement aux utilisateurs appartenant à un groupe particulier
la source