Saya ingin pengguna di situs dapat mengunduh file yang jalurnya dikaburkan sehingga mereka tidak dapat langsung diunduh.
Misalnya, saya ingin URLnya seperti ini: http://example.com/download/?f=somefile.txt
Dan di server, saya tahu bahwa semua file yang dapat diunduh berada di folder /home/user/files/
.
Apakah ada cara untuk membuat Django melayani file itu untuk diunduh sebagai lawan mencoba menemukan URL dan Tampilan untuk menampilkannya?
Jawaban:
Untuk "terbaik dari kedua dunia" Anda dapat menggabungkan solusi S.Lott dengan modul xsendfile : django menghasilkan path ke file (atau file itu sendiri), tetapi penyajian file aktual ditangani oleh Apache / Lighttpd. Setelah Anda mengatur mod_xsendfile, mengintegrasikan dengan tampilan Anda membutuhkan beberapa baris kode:
Tentu saja, ini hanya akan berfungsi jika Anda memiliki kendali atas server Anda, atau perusahaan hosting Anda telah menyiapkan mod_xsendfile.
EDIT:
EDIT: Untuk
nginx
memeriksa ini , ia menggunakanX-Accel-Redirect
bukanapache
header X-Sendfile.sumber
smart_str
itu tidak berfungsi sebagaimana mestinya karena modul apache X-Sendfile tidak dapat mendekodekan string smart_str yang dikodekan. Jadi misalnya file "Örinää.mp3" tidak dapat dilayani. Dan jika seseorang menghilangkan smart_str, Django itu sendiri melempar kesalahan pengkodean ascii karena semua header dikodekan ke format ascii sebelum mengirim. Satu-satunya cara yang saya tahu untuk menghindari masalah ini adalah dengan mengurangi nama file X-sendfile menjadi yang hanya terdiri dari ascii."Unduhan" hanyalah perubahan tajuk HTTP.
Lihat http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment untuk cara merespons dengan unduhan .
Anda hanya perlu satu definisi URL untuk
"/download"
.Permintaan
GET
atauPOST
kamus akan memiliki"f=somefile.txt"
informasi.Fungsi tampilan Anda hanya akan menggabungkan jalur dasar dengan nilai "
f
", membuka file, membuat dan mengembalikan objek respons. Seharusnya kurang dari 12 baris kode.sumber
filepath = filepath.replace('..', '').replace('/', '')
Untuk solusi yang sangat sederhana namun tidak efisien atau scalable , Anda bisa menggunakan
serve
tampilan Django bawaan . Ini bagus untuk prototipe cepat atau pekerjaan sekali saja, tetapi seperti yang telah disebutkan di seluruh pertanyaan ini, Anda harus menggunakan sesuatu seperti apache atau nginx dalam produksi.sumber
S.Lott memiliki solusi "baik" / sederhana, dan elo80ka memiliki solusi "terbaik" / efisien. Ini adalah solusi "lebih baik" / menengah - tidak ada pengaturan server, tetapi lebih efisien untuk file besar daripada perbaikan naif:
http://djangosnippets.org/snippets/365/
Pada dasarnya, Django masih menangani melayani file tetapi tidak memuat semuanya ke dalam memori sekaligus. Ini memungkinkan server Anda untuk (perlahan-lahan) menyajikan file besar tanpa meningkatkan penggunaan memori.
Sekali lagi, X-SendFile S.Lott masih lebih baik untuk file yang lebih besar. Tetapi jika Anda tidak dapat atau tidak ingin repot dengan itu, maka solusi tengah ini akan memberi Anda efisiensi yang lebih baik tanpa kesulitan.
sumber
django.core.servers.httpbase
modul pribadi tidak berdokumen, yang memiliki tanda peringatan besar di bagian atas kode " JANGAN GUNAKAN UNTUK PENGGUNAAN PRODUKSI !!! ", yang telah ada dalam file sejak pertama kali dibuat . Bagaimanapun,FileWrapper
fungsi yang diandalkan oleh cuplikan ini telah dihapus di Django 1.9.Mencoba solusi @Rocketmonkeys tetapi file yang diunduh disimpan sebagai * .bin dan diberi nama acak. Tentu saja itu tidak baik. Menambahkan baris lain dari @ elo80ka memecahkan masalah.
Ini kode yang saya gunakan sekarang:
Anda sekarang dapat menyimpan file dalam direktori pribadi (bukan di dalam / media atau / public_html) dan mengeksposnya melalui Django ke pengguna tertentu atau dalam keadaan tertentu.
Semoga ini bisa membantu.
Terima kasih kepada @ elo80ka, @ S.Lott dan @Rocketmonkeys untuk jawabannya, dapatkan solusi sempurna yang menggabungkan semuanya =)
sumber
filename="%s"
di header Content-Disposition, untuk menghindari masalah dengan spasi pada nama file. Referensi: Nama file dengan spasi terpotong saat diunduh , Bagaimana cara menyandikan parameter nama file header Content-Disposition di HTTP?FileWrapper(open(path.abspath(file_name), 'rb'))
FileWrapper
telah dihapus sejak Django 1.9from wsgiref.util import FileWrapper
Hanya menyebutkan objek FileResponse yang tersedia di Django 1.10
Sunting: Hanya berlari ke jawaban saya sendiri sambil mencari cara mudah untuk melakukan streaming file melalui Django, jadi di sini adalah contoh yang lebih lengkap (untuk masa depan saya). Diasumsikan bahwa nama FileField adalah
imported_file
views.py
urls.py
sumber
Disebutkan di atas bahwa metode mod_xsendfile tidak memungkinkan untuk karakter non-ASCII dalam nama file.
Untuk alasan ini, saya memiliki tambalan yang tersedia untuk mod_xsendfile yang akan memungkinkan file apa pun untuk dikirim, asalkan namanya dikodekan url, dan header tambahan:
Dikirim juga.
http://ben.timby.com/?p=149
sumber
Coba: https://pypi.python.org/pypi/django-sendfile/
"Abstraksi untuk melepas file unggahan ke server-web (mis. Apache dengan mod_xsendfile) begitu Django telah memeriksa izin, dll."
sumber
Anda harus menggunakan apis sendfile yang diberikan oleh server populer seperti
apache
ataunginx
dalam produksi. Bertahun-tahun saya menggunakan api sendfile dari server ini untuk melindungi file. Kemudian dibuat aplikasi django berbasis middleware sederhana untuk tujuan ini cocok untuk tujuan pengembangan & produksi. Anda dapat mengakses kode sumber di sini .UPDATE: di
python
penyedia versi baru menggunakan DjangoFileResponse
jika tersedia dan juga menambahkan dukungan untuk banyak implementasi server dari lighthttp, caddy ke hiawathaPemakaian
fileprovider
aplikasi keINSTALLED_APPS
pengaturan,fileprovider.middleware.FileProviderMiddleware
keMIDDLEWARE_CLASSES
pengaturanFILEPROVIDER_NAME
pengaturan kenginx
atauapache
dalam produksi, secara default itupython
untuk tujuan pengembangan.di tampilan berbasis fungsi atau class Anda mengatur
X-File
nilai header respons ke path absolut ke file. Sebagai contoh,django-fileprovider
diterapkan sedemikian rupa sehingga kode Anda hanya perlu modifikasi minimum.Konfigurasi nginx
Untuk melindungi file dari akses langsung, Anda dapat mengatur konfigurasi sebagai
Di sini
nginx
menetapkan url lokasi/files/
hanya akses internal, jika Anda menggunakan konfigurasi di atas, Anda dapat mengatur X-File sebagai,Dengan melakukan ini dengan konfigurasi nginx, file akan dilindungi & Anda juga dapat mengontrol file dari Django
views
sumber
Django menyarankan Anda menggunakan server lain untuk melayani media statis (server lain yang berjalan pada mesin yang sama baik-baik saja.) Mereka merekomendasikan penggunaan server seperti lighttp .
Ini sangat sederhana untuk diatur. Namun. jika 'somefile.txt' dihasilkan berdasarkan permintaan (konten bersifat dinamis) maka Anda mungkin ingin django menyajikannya.
Django Docs - File Statis
sumber
sumber
Proyek lain untuk melihat: http://readthedocs.org/docs/django-private-files/en/latest/usage.html Tampak menjanjikan, belum mengujinya sendiri belum.
Pada dasarnya proyek abstrak konfigurasi mod_xsendfile dan memungkinkan Anda untuk melakukan hal-hal seperti:
sumber
django-private-files
...Saya telah menghadapi masalah yang sama lebih dari sekali dan diimplementasikan menggunakan modul xsendfile dan dekorator tampilan autent the django-filelibrary . Jangan ragu untuk menggunakannya sebagai inspirasi untuk solusi Anda sendiri.
https://github.com/danielsokolowski/django-filelibrary
sumber
Memberikan akses yang dilindungi ke folder html statis menggunakan https://github.com/johnsensible/django-sendfile : https://gist.github.com/iutinvg/9907731
sumber
Saya melakukan proyek tentang ini. Anda dapat melihat repo github saya:
https://github.com/nishant-boro/django-rest-framework-download-expert
Modul ini menyediakan cara sederhana untuk menyajikan file untuk diunduh dalam kerangka istirahat Django menggunakan modul Apache Xsendfile. Ini juga memiliki fitur tambahan untuk melayani unduhan hanya untuk pengguna yang termasuk dalam kelompok tertentu
sumber