Bagaimana cara menyandikan parameter pengaturan nama file Content-Disposition di HTTP?

Aplikasi web yang ingin memaksa pengunduhan sumber daya, alih-alih >Content-Disposition dalam respons HTTP dari formulir:

Content-Disposition: attachment; filename=FILENAME

Parameter filename dapat digunakan untuk menentukan nama file di mana sumber daya dimuat oleh browser. RFC 2183 (Content-Disposition), bagaimanapun, mengatakan 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, oleh karena itu, Nama File Disposisi Konten) menjadi US-ASCII. Kami mengakui keinginan untuk mengizinkan set karakter sewenang-wenang dalam nama file, tetapi ini berada di luar cakupan dokumen ini untuk menentukan mekanisme yang diperlukan.

Namun demikian, ada bukti empiris bahwa sebagian besar browser web populer saat ini tampaknya memungkinkan karakter selain US-ASCII, sejauh ini (karena kurangnya standar) untuk tidak setuju pada skema pengkodean dan set karakter karakter set nama file. Pertanyaannya adalah, apa skema dan penyandian yang berbeda yang digunakan oleh browser populer jika nama file adalah "naïvefile" (tanpa tanda kutip dan di mana huruf ketiga U + 00EF) perlu dikodekan ke dalam header Content-Disposition?

Untuk keperluan pertanyaan ini, browser populer adalah:

  • Firefox
  • Internet Explorer
  • Safari
  • Google chrome
  • Opera
444
18 сент. diatur oleh Atif Aziz 18 September . 2008-09-18 18:25 '08 pada 18:25 2008-09-18 18:25
@ 17 balasan

Ada diskusi tentang masalah ini, termasuk referensi untuk pengujian browser dan kompatibilitas ke belakang, dalam RFC 5987 yang diusulkan, "Kumpulan Karakter dan Pengkodean Bahasa untuk Parameter Bidang Header Protokol Hiperteks (HTTP).

RFC 2183 menetapkan bahwa tajuk tersebut harus dikodekan sesuai dengan RFC 2184 , yang sudah usang RFC 2231 , dibahas di atas dalam konsep RFC.

79
18 сент. Jawabannya diberikan oleh Jim 18 Sep. 2008-09-18 18:39 '08 pada 18:39 2008-09-18 18:39

Saya tahu ini posting lama, tetapi masih sangat penting. Saya menemukan bahwa browser modern mendukung rfc5987, yang memungkinkan Anda untuk menyandikan utf-8, persentasenya disandikan (disandikan oleh URL). Kemudian Naïve file.txt menjadi:

 Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt 

Safari (5) tidak mendukung ini. Sebagai gantinya, Anda harus menggunakan standar Safari untuk menulis nama file secara >

 Content-Disposition: attachment; filename=Naïve file.txt 

IE8 dan yang lebih lama tidak mendukungnya, dan Anda perlu menggunakan standar IE untuk pengkodean utf-8, kode persentase:

 Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt 

Di ASP.Net saya menggunakan kode berikut:

Berikut adalah kode yang saya gunakan saat ini. Saya masih harus mendukung IE8, jadi saya tidak bisa menghi>

 private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c); private string MakeAndroidSafeFileName(string fileName) { char[] newFileName = fileName.ToCharArray(); for (int i = 0; i < newFileName.Length; i++) { if (!AndroidAllowedChars.ContainsKey(newFileName[i])) newFileName[i] = '_'; } return new string(newFileName); } 

@ TomZ: Saya menguji di IE7 dan IE8, dan ternyata saya tidak perlu menghindari tanda kutip ('). Apakah Anda memiliki contoh di mana ia gagal?

@Dave Van den Eynde: menggabungkan dua nama file dalam satu baris, seperti pada RFC6266, dengan pengecualian Android dan IE7 + 8, dan saya memperbarui kode untuk mencerminkan ini. Terima kasih atas sarannya.

@Thilo: Saya tidak tahu tentang GoodReader atau browser lainnya. Anda mungkin dapat menggunakan pendekatan Android.

@Alex Zhukovsky: Saya tidak tahu mengapa, tapi, seperti yang dibahas di Connect , sepertinya tidak bekerja dengan baik.

297
19 июля '11 в 13:34 2011-07-19 13:34 Jawaban diberikan oleh Martin Ørding-Thomsen 19 Juli '11 pada 13:34 2011-07-19 13:34

Ada alternatif sederhana dan sangat andal: gunakan URL yang berisi nama file yang diinginkan .

Ketika nama setelah slash terakhir adalah yang Anda butuhkan, Anda tidak perlu header tambahan!

Trik ini berfungsi:

 /real_script.php/fake_filename.doc 

Dan jika server Anda mendukung penulisan u>mod_rewrite Apache), Anda dapat sepenuhnya menyembunyikan bagian skrip.

Karakter dalam URL harus dalam UTF-8, standarnya adalah byte-by-byte:

 /mot%C3%B6rhead # motörhead 
145
19 окт. Kornel menjawab 19 Okt. 2008-10-19 21:26 '08 pada 21:26 2008-10-19 21:26

RFC 6266 menjelaskan "Menggunakan Field Header Content-Disposition dalam Hypertext Transfer Protocol (HTTP)." Kutipan dari ini:

6. Masalah internasionalisasi

Parameter " filename* " ( Bagian 4.3 ), menggunakan pengkodean spesifik dalam [ RFC5987 ], memungkinkan server untuk mengirimkan karakter di luar Set Karakter ISO-8859-1, dan secara opsional menentukan bahasa yang akan digunakan.

Dan di bagian:

Contoh ini mirip dengan yang di atas, tetapi menambahkan parameter nama file "untuk kompatibilitas dengan agen kustom yang tidak menerapkan RFC 5987 :

 Content-Disposition: attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates 

Catatan Agen pengguna ini yang tidak mendukung penyandian RFC 5987 mengabaikan " filename* " ketika ini terjadi setelah " filename ".

Lampiran D juga memiliki daftar saran yang panjang untuk meningkatkan interoperabilitas. Dia juga menunjuk ke situs yang membandingkan implementasi . Tes saat ini dari semua lintasan, cocok untuk nama file umum, termasuk:

  • attwithisofnplain : nama file ISO-8859-1 sederhana dengan tanda kutip ganda dan tanpa pengodean. Ini membutuhkan nama file yang ISO-8859-1 dan tidak mengandung tanda persen, setidaknya tidak sebelum digit heksadesimal.
  • attfnboth : dua parameter dalam urutan yang dijelaskan di atas. Seharusnya berfungsi untuk sebagian besar nama file di sebagian besar browser, walaupun IE8 akan menggunakan parameter " filename ".

RFC 5987 ini pada gilirannya mengacu pada RFC 2231 , yang menjelaskan format aktual. 2231 terutama ditujukan untuk surat, dan 5987 memberi tahu kami bagian mana yang dapat digunakan untuk header HTTP. Jangan bingung hal ini dengan header MIME yang digunakan di dalam tubuh HTTP multipart/form-data , yang diatur oleh RFC 2388 ( bagian 4.4 khususnya) dan proyek HTML 5 .

54
05 янв. jawabannya diberikan MvG 05 Januari. 2014-01-05 15:48 '14 pada 15:48 2014-01-05 15:48

Dokumen berikut yang berkaitan dengan proyek RFC , ditunjukkan oleh Jim, dalam jawabannya selanjutnya menjawab pertanyaan dan, tentu saja, ada di sini:

Contoh uji untuk header HTTP Disposisi Konten dan penyandian RFC 2231/2047

16
18 сент. jawabannya diberikan oleh Atif Aziz 18 September . 2008-09-18 19:08 '08 pada 19:08 2008-09-18 19:08

di asp.net mvc2, saya menggunakan sesuatu seperti ini:

 return File( tempFile , "application/octet-stream" , HttpUtility.UrlPathEncode(fileName) ); 

Saya berasumsi bahwa jika Anda tidak menggunakan mvc (2), Anda dapat menyandikan nama file menggunakan

 HttpUtility.UrlPathEncode(fileName) 
10
15 июля '10 в 18:08 2010-07-15 18:08 Balasan diberikan oleh Elmer pada 15 Juli '10 pada 18:08 2010-07-15 18:08

Masukkan nama file dengan tanda kutip ganda. Menyelesaikan masalah bagi saya. Ini dia:

 Content-Disposition: attachment; filename="My Report.doc" 

http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download

8
10 июля '15 в 18:01 2015-07-10 18:01 Jawaban diberikan oleh Dmitry Kaigorodov 10 Juli '15 pada 18:01 2015-07-10 18:01

Saya menggunakan potongan kode berikut untuk penyandian (dengan asumsi bahwa nama file adalah nama file dan ekstensi file, mis. Test.txt):


PHP:

 fileName = request.getHeader ( "user-agent" ).contains ( "MSIE" ) ? URLEncoder.encode ( fileName, "utf-8") : MimeUtility.encodeWord ( fileName ); response.setHeader ( "Content-disposition", "attachment; filename=\"" + fileName + "\""); 
8
19 апр. Vassilen Dontchev diposting pada 19 April 2013-04-19 14:29 '13 pada 14:29 2013-04-19 14:29

Di ASP.NET Web API, saya url menyandikan nama file:

 public static class HttpRequestMessageExtensions { public static HttpResponseMessage CreateFileResponse(this HttpRequestMessage request, byte[] data, string filename, string mediaType) { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); var stream = new MemoryStream(data); stream.Position = 0; response.Content = new StreamContent(stream); response.Content.Headers.ContentType = new MediaTypeHeaderValue(mediaType); // URL-Encode filename // Fixes behavior in IE, that filenames with non US-ASCII characters // stay correct (not "_utf-8_.......=_="). var encodedFilename = HttpUtility.UrlEncode(filename, Encoding.UTF8); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = encodedFilename }; return response; } } 

2019

8
25 июня '15 в 11:10 2015-06-25 11:10 jawabannya diberikan oleh martinoss pada 25 Juni '15 di 11:10 2015-06-25 11:10

Jika Anda menggunakan backend nodejs, Anda dapat menggunakan kode berikut, yang saya temukan di sini

5
25 сент. jawabannya diberikan oleh Emanuele Spatola 25 September . 2015-09-25 15:45 '15 pada 15:45 2015-09-25 15:45

Saya menguji kode berikut di semua browser utama, termasuk Peneliti yang lebih tua (melalui mode kompatibilitas), dan berfungsi dengan baik di mana-mana:

5
31 мая '12 в 18:48 2012-05-31 18:48 jawabannya diberikan oleh Stano pada 31 Mei '12 pada 18:48 2012-05-31 18:48

Dalam skrip "download.php" saya (berdasarkan blogpost ini dan contoh pengujian ini ).

 $il1_filename = utf8_decode($filename); $to_underscore = "\"\\#*;:|<>/?"; $safe_filename = strtr($il1_filename, $to_underscore, str_repeat("_", strlen($to_underscore))); header("Content-Disposition: attachment; filename=\"$safe_filename\"" .( $safe_filename === $filename ? "" : "; filename*=UTF-8''".rawurlencode($filename) )); 

Ini menggunakan metode nama file standar = "..." jika hanya karakter iso-latin1 dan "safe" yang digunakan; jika tidak, ia menambahkan nama file * = UTF-8 '', yang dikodekan oleh URL. Menurut kasus uji khusus ini , itu harus bekerja dari MSIE9 ke atas, serta dari FF, Chrome, Safari terbaru; pada versi yang lebih rendah dari MSIE, itu harus menyarankan nama file yang berisi versi nama file ISO8859-1, dengan garis bawah untuk karakter yang tidak termasuk dalam pengkodean ini.

Catatan akhir: maks. Ukuran untuk setiap bidang tajuk adalah 8190 byte per apache. UTF-8 dapat memuat hingga empat byte per karakter; setelah rawurlencode adalah x3 = 12 byte per karakter. Cukup tidak efisien, tetapi secara teoretis secara teori dimungkinkan untuk memiliki lebih dari 600 "senyum"% F0% 9F% 98% 81 dalam nama file.

4
05 апр. jawab diberikan renergy 05 Apr 2015-04-05 18:45 '15 jam 6:45 sore 2015-04-05 18:45

Di PHP, ini yang saya lakukan (jika nama file dikodekan dalam UTF8):

 header('Content-Disposition: attachment;' . 'filename="' . addslashes(utf8_decode($filename)) . '";' . 'filename*=utf-8\'\'' . rawurlencode($filename)); 

Diuji terhadap IE8-11, Firefox dan Chrome.
Jika browser dapat mengartikan nama file * = utf-8, itu akan menggunakan versi UTF8 dari nama file, jika tidak maka akan menggunakan nama file yang di-decode. Jika nama file Anda berisi karakter yang tidak dapat direpresentasikan dalam ISO-8859-1, Anda mungkin perlu menggunakan iconv sebagai gantinya.

3
20 мая '16 в 15:47 2016-05-20 15:47 jawabannya diberikan oleh Gustav pada 20 Mei '16 pukul 15:47 2016-05-20 15:47

Solusi ASP klasik

Sebagian besar browser modern sekarang mendukung Filename sebagai UTF-8 , tetapi seperti halnya dengan solusi unggah file yang saya gunakan, itu didasarkan pada FreeASPUpload.Net (situs tidak lagi ada, tautannya menunjuk ke archive.org ), itu tidak berfungsi ingin parsing biner bergantung pada pembacaan string single-encode ASCII byte yang berfungsi dengan baik ketika Anda mentransmisikan data yang dikodekan UTF-8 sampai Anda mendapatkan karakter yang ASCII tidak mendukung.

Namun, saya berhasil menemukan solusi untuk membaca kode dan menganalisisnya sebagai UTF-8.

Net memuat file ASP dengan menerapkan fungsi BytesToString() dari include_aspuploader.asp dalam kode saya sendiri, yang saya bisa dapatkan nama file UTF-8 . 


Tautan yang bermanfaat

1
23 мая '16 в 15:17 2016-05-23 15:17 jawabannya diberikan oleh Lankymart pada 23 Mei '16 pukul 15:17 2016-05-23 15:17

Kami memiliki masalah yang sama dalam aplikasi web, dan sebagai hasilnya saya membaca nama file dari <input type="file"> HTML dan menginstalnya dalam pengkodean url di HTML <input type="hidden"> . Tentu saja, kami harus menghapus jalur seperti "C: \ fakepath", yang dikembalikan oleh beberapa browser.

Tentu saja, ini tidak >

-1
27 янв. Jawaban diberikan oleh Andrei I pada 27 Januari 2015-01-27 14:54 '15 pada 14:54 2015-01-27 14:54

Saya biasanya menyandikan nama file URL (dengan% xx) dan sepertinya berfungsi di semua browser. Anda mungkin ingin melakukan beberapa tes.

-2
18 сент. jawabannya diberikan oleh Dario Solera 18 September. 2008-09-18 18:28 '08 pada 18:28 2008-09-18 18:28

Saya menemukan solusi yang berfungsi untuk semua browser saya (mis., Semua browser yang saya instal - IE8, FF16, Opera 12, Chrome 22).

Solusi saya dijelaskan dalam topik lain: Java servlet mengunduh nama file karakter khusus

Keputusan saya didasarkan pada cara browser mencoba membaca nilai dari parameter filename . Jika parameter filename (misalnya, filename*=utf-8''test.xml ) tidak memiliki penyandian, peramban mengharapkan nilai ini dikodekan dalam penyandian peramban asli.

Browser yang berbeda mengharapkan penyandian internal yang sangat baik. Biasanya, penyandian browser awal adalah utf-8 (FireFox, Opera, Chrome). Tetapi pengkodean IE asli adalah Win-1250. (Saya tidak tahu apa-apa tentang peramban lain.)

Oleh karena itu, jika kita meletakkan nilai dalam parameter, yang dikodekan dengan utf-8 / win-1250 sesuai dengan browser pengguna, itu harus berfungsi. Setidaknya itu bekerja untuk saya.

Singkatnya, jika kita memiliki file bernama omáčka.xml ,
untuk FireFox, Opera, dan Chrome, saya akan menjawab tajuk ini (disandikan dalam utf-8):

 Content-Disposition: attachment; filename="omáčka.xml" 

dan untuk IE, saya menanggapi header ini (disandikan dalam win-1250):

 Content-Disposition: attachment; filename="omáèka.jpg" 

Contoh Java di posting saya yang disebutkan di atas.

-3
13 нояб. jawabannya diberikan sporak 13 Nov 2012-11-13 17:43 '12 pada 17:43 2012-11-13 17:43

Pertanyaan lain tentang tag tag atau Ajukan pertanyaan