Aplikasi web yang ingin memaksa sumber daya untuk diunduh daripada secara langsung diberikan di browser Web mengeluarkan Content-Disposition
header dalam respons HTTP dari formulir:
Content-Disposition: attachment; filename=FILENAME
The filename
parameter dapat digunakan untuk menyarankan nama untuk file mana sumber daya diunduh oleh browser. RFC 2183 (Content-Disposition), bagaimanapun, menyatakan dalam bagian 2.3 (Parameter Nama File) bahwa nama file hanya dapat menggunakan karakter US-ASCII:
Tata bahasa [RFC 2045] saat ini membatasi nilai parameter (dan karenanya nama file Content-Disposition) menjadi US-ASCII. Kami mengakui keinginan besar untuk mengizinkan set karakter sewenang-wenang dalam nama file, tetapi ini berada di luar cakupan dokumen ini untuk menentukan mekanisme yang diperlukan.
Ada bukti empiris, bagaimanapun, bahwa browser Web paling populer saat ini tampaknya mengizinkan karakter non-AS-ASCII (karena kurangnya standar) tidak setuju pada skema pengkodean dan spesifikasi karakter yang ditetapkan dari nama file. Pertanyaannya kemudian, apa saja berbagai skema dan penyandian yang digunakan oleh peramban populer jika nama file "naïvefile" (tanpa tanda kutip dan di mana huruf ketiga adalah U + 00EF) yang perlu dikodekan ke dalam header Content-Disposition?
Untuk keperluan pertanyaan ini, browser populer adalah:
- Firefox
- Internet Explorer
- Safari
- Google Chrome
- Opera
sumber
Content-Disposition: attachment
.Jawaban:
Ada diskusi mengenai hal ini, termasuk tautan ke pengujian peramban dan kompatibilitas ke belakang, dalam RFC 5987 yang diusulkan , "Kumpulan Karakter dan Pengkodean Bahasa untuk Parameter Header Protocol Hypertext Transfer Protocol (HTTP)."
RFC 2183 menunjukkan bahwa tajuk tersebut harus dikodekan menurut RFC 2184 , yang sudah usang oleh RFC 2231 , dicakup oleh konsep RFC di atas.
sumber
Content-Disposition: filename="foo, bar.pdf"
. Hasilnya adalah firefox mengunduh file dengan benar tetapi menjaga.part
ekstensi (misfoo,bar.pdf-1.part
.). Kemudian, tentu saja file tidak akan terbuka dengan benar karena aplikasi tidak terkait.part
. Karakter ASCII lainnya tampaknya berfungsi dengan baik.Saya tahu ini adalah pos lama tetapi masih sangat relevan. Saya telah menemukan bahwa browser modern mendukung rfc5987, yang memungkinkan encoding utf-8, persentase yang disandikan (url-encoded). Kemudian Naïve file.txt menjadi:
Safari (5) tidak mendukung ini. Sebagai gantinya, Anda harus menggunakan standar Safari untuk menulis nama file secara langsung di header utf-8 Anda yang dikodekan:
IE8 dan yang lebih lama juga tidak mendukungnya dan Anda perlu menggunakan standar IE untuk pengkodean utf-8, persentase yang disandikan:
Di ASP.Net saya menggunakan kode berikut:
Saya menguji di atas menggunakan IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Pembaruan November 2013:
Berikut adalah kode yang saya gunakan saat ini. Saya masih harus mendukung IE8, jadi saya tidak bisa menghilangkan bagian pertama. Ternyata peramban di Android menggunakan pengelola unduhan bawaan Android dan tidak dapat mengurai nama file dengan cara standar.
Di atas sekarang diuji di IE7-11, Chrome 32, Opera 12, FF25, Safari 6, menggunakan nama file ini untuk diunduh: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§! # ¤% & () = `@ £ $ {{]} + ´¨ ^ ~ '-_,;. txt
Pada IE7 berfungsi untuk beberapa karakter tetapi tidak semua. Tapi siapa yang peduli dengan IE7 saat ini?
Ini adalah fungsi yang saya gunakan untuk menghasilkan nama file yang aman untuk Android. Perhatikan bahwa saya tidak tahu karakter mana yang didukung di Android tetapi saya telah menguji apakah ini berfungsi:
@ TomZ: Saya diuji di IE7 dan IE8 dan ternyata saya tidak perlu melarikan diri tanda kutip ('). Apakah Anda memiliki contoh gagal?
@Dave Van den Eynde: Menggabungkan dua nama file pada satu baris sesuai dengan RFC6266 berfungsi kecuali untuk Android dan IE7 + 8 dan saya telah memperbarui kode untuk mencerminkan ini. Terima kasih atas sarannya.
@Thilo: Tidak tahu tentang GoodReader atau non-browser lainnya. Anda mungkin beruntung menggunakan pendekatan Android.
@Alex Zhukovskiy: Saya tidak tahu mengapa, tetapi seperti yang dibahas di Connect sepertinya tidak berfungsi dengan baik.
sumber
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
dan lewati sniffing browser? Apakah itu akan berhasil?Tidak ada cara interoperable untuk menyandikan nama-nama non-ASCII di
Content-Disposition
. Kompatibilitas browser berantakan .The sintaks teoritis yang benar untuk penggunaan UTF-8 di
Content-Disposition
sangat aneh:filename*=UTF-8''foo%c3%a4
(ya, itu tanda bintang, dan tanpa tanda kutip kecuali kutipan tunggal kosong di tengah)Header ini agak-tidak-cukup-standar ( HTTP / 1.1 spec mengakui keberadaannya , tetapi tidak mengharuskan klien untuk mendukungnya).
Ada alternatif sederhana dan sangat kuat: gunakan URL yang berisi nama file yang Anda inginkan .
Ketika nama setelah slash terakhir adalah yang Anda inginkan, Anda tidak perlu header tambahan!
Trik ini berfungsi:
Dan jika server Anda mendukung penulisan ulang URL (misalnya
mod_rewrite
di Apache) maka Anda dapat sepenuhnya menyembunyikan bagian skrip.Karakter dalam URL harus dalam UTF-8, urlencoded byte-by-byte:
sumber
/:id/:filename
Metode benar-benar sederhana dan karya, terima kasih!Content-Disposition
dan menciptakan nama file yang sangat menarik bukan (mereka akan dihasilkan dari jalan Anda). Jadi satu-satunya solusi untuk menjaga kewarasan seseorang hanya menetapkanContent-Disposition: attachment
dan melewati nama file yang diinginkan sebagai komponen jalur terakhir:RFC 6266 menjelaskan " Penggunaan Bidang Header Konten-Disposisi di Hypertext Transfer Protocol (HTTP) ". Mengutip dari itu:
Dan di bagian contoh mereka :
Dalam Lampiran D ada juga daftar panjang saran untuk meningkatkan interoperabilitas. Itu juga menunjuk ke situs yang membandingkan implementasi . Tes menyeluruh yang sesuai untuk nama file umum meliputi:
filename
parameter " ".Itu RFC 5987 pada gilirannya referensi RFC 2231 , yang menggambarkan format aktual. 2231 terutama untuk surat, dan 5987 memberi tahu kami bagian mana yang dapat digunakan untuk header HTTP juga. Jangan bingung dengan header MIME yang digunakan di dalam tubuh
multipart/form-data
HTTP , yang diatur oleh RFC 2388 ( bagian 4.4 khususnya) dan konsep HTML 5 .sumber
Dokumen berikut yang ditautkan dari draft RFC yang disebutkan oleh Jim dalam jawabannya menjawab pertanyaan lebih lanjut dan tentunya patut dicatat di sini:
Uji Kasus untuk header Disposisi Konten HTTP dan Pengodean RFC 2231/2047
sumber
di asp.net mvc2 saya menggunakan sesuatu seperti ini:
Saya kira jika Anda tidak menggunakan mvc (2) Anda hanya bisa menyandikan nama file menggunakan
sumber
Masukkan nama file dalam tanda kutip ganda. Memecahkan masalah bagi saya. Seperti ini:
http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
Saya sudah menguji beberapa opsi. Browser tidak mendukung spesifikasi dan bertindak secara berbeda, saya percaya tanda kutip ganda adalah pilihan terbaik.
sumber
&
,%
,#
dll Jadi itu memecahkan itu.Saya menggunakan potongan kode berikut untuk penyandian (dengan asumsi fileName berisi nama file dan ekstensi file, yaitu: test.txt):
PHP:
Jawa:
sumber
rawurlencode
dalam PHP setidaknya untukfilename*=
header disposisi sejakvalue-chars
digunakan dalamext-value
RFC 6266-> RFC 5987 (lihat tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section -3.2.1 ) tidak memungkinkan ruang tanpa persen melarikan diri (filename=
, di sisi lain, tampaknya itu dapat memungkinkan ruang tanpa melarikan diri sama sekali meskipun hanya ASCII yang harus hadir di sini). Tidak perlu dikodekan dengan ketatnya rawurlencode, sehingga beberapa karakter dapat dihapusDi ASP.NET Web API, saya url menyandikan nama file:
sumber
Saya menguji kode berikut di semua browser utama, termasuk Penjelajah yang lebih lama (melalui mode kompatibilitas), dan bekerja dengan baik di mana-mana:
sumber
Saya berakhir dengan kode berikut dalam skrip "download.php" saya (berdasarkan blogpost ini dan beberapa test case ).
Ini menggunakan cara standar filename = "..." selama hanya ada karakter iso-latin1 dan "aman" yang digunakan; jika tidak, ia menambahkan nama file * = UTF-8 '' cara disandikan url. Menurut kasus uji khusus ini , itu harus bekerja dari MSIE9 ke atas, dan pada FF, Chrome, Safari baru-baru ini; pada versi MSIE yang lebih rendah, ia harus menawarkan nama file yang mengandung versi ISO8859-1 nama file, dengan menggarisbawahi karakter yang tidak ada dalam pengkodean ini.
Catatan akhir: maks. ukuran untuk setiap bidang header adalah 8190 byte pada apache. UTF-8 dapat mencapai hingga empat byte per karakter; setelah rawurlencode, itu adalah x3 = 12 byte per satu karakter. Cukup tidak efisien, tetapi secara teori masih mungkin untuk memiliki lebih dari 600 "senyum"% F0% 9F% 98% 81 dalam nama file.
sumber
Jika Anda menggunakan backend nodejs Anda dapat menggunakan kode berikut yang saya temukan di sini
sumber
encodeURI(str)
. Sebagai contoh dengan tanggal dalam nama file:encodeURIComponent('"Kornél Kovács 1/1/2016')
=> "Kornél Kovács 1% 2F1% 2F2016" vs.encodeURI('"Kornél Kovács 1/1/2016')
=> "Kornél Kovács 1/1/2016"Dalam PHP ini melakukannya untuk saya (dengan asumsi nama file dikodekan UTF8):
Diuji terhadap IE8-11, Firefox dan Chrome.
Jika browser dapat menginterpretasikan nama file * = utf-8 ia akan menggunakan versi nama file UTF8, jika tidak maka ia akan menggunakan nama file yang di-decode. Jika nama file Anda mengandung karakter yang tidak dapat direpresentasikan dalam ISO-8859-1, Anda mungkin ingin mempertimbangkan untuk menggunakannya
iconv
.sumber
Hanya pembaruan sejak saya mencoba semua hal ini hari ini sebagai tanggapan terhadap masalah pelanggan
sumber
Kerangka kerja PHP Symfony 4 ada
$filenameFallback
diHeaderUtils::makeDisposition
. Anda dapat melihat ke dalam fungsi ini untuk perincian - mirip dengan jawaban di atas.Contoh penggunaan:
sumber
Solusi ASP Klasik
Sebagian besar peramban modern mendukung lewat
Filename
sepertiUTF-8
sekarang tetapi seperti halnya dengan solusi Unggah File yang saya gunakan yang didasarkan pada FreeASPUpload.Net (situs tidak ada lagi, titik tautan ke archive.org ) itu tidak akan berfungsi sebagai penguraian dari biner bergantung pada membaca string ASCII enkode byte tunggal, yang berfungsi dengan baik ketika Anda melewatkan data yang disandikan UTF-8 hingga Anda mendapatkan karakter yang ASCII tidak mendukung.Namun saya dapat menemukan solusi untuk mendapatkan kode untuk membaca dan mengurai biner sebagai UTF-8.
Kredit digunakan untuk Upload File ASP Murni dengan menerapkan
BytesToString()
fungsi dariinclude_aspuploader.asp
dalam kode saya sendiri, saya dapat membuatUTF-8
nama file berfungsi.Tautan yang Berguna
Multipart / formulir-data dan UTF-8 dalam aplikasi ASP Classic
Perbedaan format Unicode, UTF, ASCII, ANSI
sumber
Kami memiliki masalah yang sama dalam aplikasi web, dan akhirnya dengan membaca nama file dari HTML
<input type="file">
, dan pengaturan itu dalam bentuk yang dikodekan-url dalam HTML baru<input type="hidden">
. Tentu saja kami harus menghapus path seperti "C: \ fakepath \" yang dikembalikan oleh beberapa browser.Tentu saja ini tidak secara langsung menjawab pertanyaan OPs, tetapi dapat menjadi solusi bagi orang lain.
sumber
Saya biasanya URL-encode (dengan% xx) nama file, dan tampaknya berfungsi di semua browser. Anda mungkin ingin melakukan beberapa tes.
sumber