Kaip koduoti failo pavadinimo nustatymo parametrą „Content-Disposition“ HTTP?

Žiniatinklio programos, norinčios priversti atsisiųsti išteklius, o ne tiesiogiai rodyti jas žiniatinklio naršyklėje, HTTP formos atsakyme skambina Content-Disposition antraštė:

Content-Disposition: attachment; filename=FILENAME

filename parametras gali būti naudojamas norint nurodyti failo, į kurį naršyklė įkelia išteklių, pavadinimą. Tačiau RFC 2183 (turinio disponavimas) 2.3 skirsnyje (failo pavadinimo parametras) sakoma, kad failo pavadinime gali būti naudojami tik US-ASCII simboliai:

Dabartinė gramatika [RFC 2045] apriboja parametrų reikšmes (ir, atitinkamai, turinio dislokavimo failų vardus) į US-ASCII. Mes pripažįstame, kad pageidautina leisti savavališkus simbolių rinkinius failų pavadinimuose, tačiau tai nėra šio dokumento taikymo sritis, siekiant nustatyti būtinus mechanizmus.

Nepaisant to, yra empirinių įrodymų, kad šiandien populiariausios žiniatinklio naršyklės, atrodo, leidžia kitokius simbolius nei JAV-ASCII (dėl standarto trūkumo) nesutikti dėl kodavimo schemos ir failo pavadinimo simbolių rinkinio simbolių rinkinio. Kyla klausimas, kokios yra skirtingos populiarių naršyklių naudojamos schemos ir koduotės, jei failo pavadinimas yra „naivus failas“ (be kabučių ir kur trečioji raidė U + 00EF) turi būti užkoduota į turinio dispozicijos antraštę?

Šio klausimo tikslais populiarios naršyklės yra:

  • „Firefox“
  • „Internet Explorer“
  • „Safari“
  • „Google“ chromas
  • Opera
444
18 сент. nustatė Atif Aziz 18 sep . 2008-09-18 18:25 '08 18:25 2008-09-18 18:25
@ 17 atsakymų

Aptariama ši problema, įskaitant nuorodas į naršyklės bandymus ir atgalinį suderinamumą, siūlomame RFC 5987 , „Hiperteksto protokolo antraštės lauko parametrų (HTTP) simbolių rinkinys ir kalbos kodavimas“.

RFC 2183 nurodo, kad tokios antraštės turėtų būti koduojamos pagal RFC 2184 , kuris buvo pasenęs RFC 2231 , aptartas aukščiau RFC projekte.

79
18 сент. Atsakymą pateikė Jim . 2008-09-18 18:39 '08 at 18:39 2008-09-18 18:39

Žinau, kad tai yra senas pranešimas, tačiau jis vis dar yra labai svarbus. Radau, kad šiuolaikinės naršyklės palaiko rfc5987, kuri leidžia koduoti utf-8, procentas yra užkoduotas (koduojamas pagal URL). Tada „Naïve file.txt“ tampa:

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

„Safari“ (5) to nepalaiko. Vietoj to, turėtumėte naudoti „Safari“ standartą, norėdami įrašyti failo pavadinimą tiesiai į utf-8 koduotą antraštę:

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

IE8 ir vyresni jos nepalaiko, ir jums reikia naudoti IE standartą utf-8 kodavimui, procentinį kodą:

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

ASP.Net naudoju šį kodą:

 string contentDisposition; if (Request.Browser.Browser == "IE"  (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0")) contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName); else if (Request.UserAgent != null  Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android) contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\""; else contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName); Response.AddHeader("Content-Disposition", contentDisposition); 

Pirmiau minėtas failas buvo išbandytas naudojant IE7-11, „Chrome 32“, „Opera 12“, „FF25“, „Safari 6“, naudodami šį atsisiuntimo pavadinimą: 你好 abcABCæøåÆ Å Å ä ä §! # ¤% () = `@ £ $ € [[]} + ^ ~ -_,. Txt

„IE7“ jis veikia kai kuriems simboliams, bet ne visiems. Bet kas dabar rūpinasi IE7?

Tai funkcija, kurią naudoju kuriant saugius „Android“ failų pavadinimus. Atminkite, kad nežinau, kurie simboliai yra palaikomi „Android“, bet ką aš išbandžiau, kad jie veikia:

Connect“ , neatrodo, kad jis gerai veikia. 

297
19 июля '11 в 13:34 2011-07-19 13:34 Atsakymą pateikė Martin Ørding-Thomsen, liepos 19 d., 11 val., 13:34 2011-07-19 13:34

Yra paprasta ir labai patikima alternatyva: naudokite URL, kuriame yra norimas failo pavadinimas .

Kai vardas po paskutinio brūkšnio yra būtinas, jums nereikia papildomų antraščių!

Šis triukas veikia:

 /real_script.php/fake_filename.doc 

Ir jei jūsų serveris palaiko URL perrašymą (pvz., „Apache“ mod_rewrite ), galite visiškai paslėpti scenarijų dalį.

URL adresų simboliai turi būti UTF-8, numatytasis yra baitinis baitas:

 /mot%C3%B6rhead # motörhead 
145
19 окт. Kornel atsakė 19 Oct. 2008-10-19 21:26 '08 21:26 2008-10-19 21:26

RFC 6266 aprašo „Turinio disponavimo antraštės lauko naudojimas hiperteksto perdavimo protokole (HTTP)“. Citata iš šios:

6. Internacionalizacijos klausimai

Parametras „ filename* “ ( 4.3 skyrius ), naudojant tam tikrą kodavimą [ RFC5987 ], leidžia serveriui perduoti simbolius už ISO-8859-1 simbolių rinkinio ir pasirinktinai nurodyti vartojamą kalbą.

Ir skyriuje:

Šis pavyzdys yra panašus į aukščiau pateiktą pavyzdį, tačiau pridėjęs failo pavadinimo parametrą suderinamumui su klientais, kurie neįgyvendina RFC 5987 :

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

Pastaba Šie naudotojo agentai, kurie nepalaiko RFC 5987 kodavimo ignoruojant „ filename* “, kai tai įvyksta po „ filename “.

D priedas taip pat turi ilgą pasiūlymų dėl sąveikos didinimo sąrašą. Jis taip pat atkreipia dėmesį į svetainę, kuri lygina įgyvendinimą . Dabartiniai visų leidimų testai, tinkami bendriems failų pavadinimams, apima:

  • attwithisofnplain : paprastas ISO-8859-1 failo pavadinimas su dvigubomis kabutėmis ir be kodavimo. Tam reikia failo pavadinimo, kuris yra ISO-8859-1 ir kuriame nėra procentinių ženklų, bent jau ne prieš šešioliktainius skaitmenis.
  • attfnboth : du parametrai aukščiau aprašyta tvarka. Daugumoje naršyklių turėtų dirbti daugeliui failų pavadinimų, nors IE8 naudos parametrą „ filename “.

Šis RFC 5987 savo ruožtu nurodo RFC 2231 , kuriame aprašomas faktinis formatas. 2231 pirmiausia skirtas paštui, o 5987 nurodo, kurios dalys gali būti naudojamos HTTP antraštėms. Nepainiokite to su MIME antraštėmis, naudojamomis HTTP multipart/form-data struktūros viduje, kurį reglamentuoja RFC 2388 (ypač 4.4 skyrius ) ir HTML 5 projektas .

54
05 янв. atsakymas pateikiamas MvG 05 jan. 2014-01-05 15:48 '14, 15:48, 2014-01-05 15:48

Toliau pateiktame dokumente, susijusiame su JIM nurodytu RFC projektu , atsakyme toliau nagrinėjamas klausimas ir, žinoma, yra čia:

Turinio disponavimo HTTP antraštės ir RFC 2231/2047 kodavimo bandymo pavyzdžiai

16
18 сент. atsakymą pateikė Atif Aziz 18 sep . 2008-09-18 19:08 '08 at 7:08 pm 2008-09-18 19:08

asp.net mvc2, aš naudoju kažką panašaus:

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

Manau, kad jei nenaudojate mvc (2), galite tiesiog koduoti failo pavadinimą naudodami

 HttpUtility.UrlPathEncode(fileName) 
10
15 июля '10 в 18:08 2010-07-15 18:08 atsakymą pateikė „ Elmer “ liepos 10 d., 18:08, 2010-07-15 18:08

Įveskite failo pavadinimą dviem kabutėmis. Išspręsta problema man. Čia jis yra:

 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 Atsakymą duoda Dmitrijus Kaigorodovas liepos 15 d. 15:01 2015-07-10 18:01

Kodavimui naudoju šiuos kodo fragmentus (darant prielaidą, kad failo pavadinimas yra failo pavadinimas ir failo plėtinys, t. Y. 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 paskelbė balandžio 19 d 2013-04-19 14:29 '13, 14:29 val. 2013-04-19 14:29

ASP.NET žiniatinklio API, aš url koduoja failo pavadinimą:

 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 atsakymą Martinoss pateikia birželio 15 d. 15 val. 11:10 2015-06-25 11:10

Jei naudojate „nodejs“ programinę įrangą, galite naudoti šį kodą, kurį aš rasiu čia

5
25 сент. atsakymą pateikė Emanuele Spatola 25 sep . 2015-09-25 15:45 '15 15:45 2015-09-25 15:45

Visuose pagrindiniuose naršyklėse, įskaitant vyresnius mokslininkus (suderinamumo režimu), išbandžiau šį kodą ir jis veikia gerai visur:

5
31 мая '12 в 18:48 2012-05-31 18:48 atsakymą Stano pateikė gegužės 31 d. 12 val. 18:48 2012-05-31 18:48

Mano „download.php“ scenarijuje (remiantis šiuo dienoraščio įrašu ir šiais bandymų pavyzdžiais ).

 $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) )); 

Tai naudoja standartinį failo pavadinimą = "...", jei naudojami tik iso-latin1 ir "saugūs" simboliai; jei ne, ji prideda failo pavadinimą * = UTF-8 '', koduotą pagal URL. Remiantis šiuo konkrečiu atveju , jis turėtų dirbti iš MSIE9 į viršų, taip pat nuo naujausios FF, „Chrome“, „Safari“; žemesnėje MSIE versijoje jis turėtų pasiūlyti failo pavadinimą, kuriame yra ISO8859-1 failo pavadinimo versija, su simboliais, kurie nėra įtraukti į šį kodavimą.

Galutinė pastaba: maks. Kiekvienos antraštės lauko dydis yra 8190 baitų per apache. UTF-8 gali būti iki keturių baitų vienam simboliui; po to, kai rawurlencode yra x3 = 12 baitų vienam simboliui. Gana neefektyvus, bet teoriškai teoriškai įmanoma, kad failo pavadinime būtų daugiau nei 600 „šypsenų“% F0% 9F% 98% 81.

4
05 апр. atsakymas duotas renergy 05 Bal 2015-04-05 18:45 '15, 18:45 pm 2015-04-05 18:45

PHP, tai padarė man (jei failo pavadinimas yra užkoduotas UTF8):

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

Išbandyta prieš IE8-11, „Firefox“ ir „Chrome“.
Jei naršyklė gali interpretuoti failo pavadinimą * = utf-8, ji naudos failo pavadinimo UTF8 versiją, kitaip ji naudos dekoduotą failo pavadinimą. Jei failo pavadinime yra simbolių, kurių negalima atvaizduoti ISO-8859-1, gali tekti naudoti iconv .

3
20 мая '16 в 15:47 2016-05-20 15:47 atsakymą pateikė Gustavas gegužės 20 d. 16, 15:47 2016-05-20 15:47

Klasikinis ASP sprendimas

Dauguma šiuolaikinių naršyklių dabar palaiko Filename kaip UTF-8 , bet kaip ir naudodamas failo įkėlimo sprendimą, jis buvo pagrįstas FreeASPUpload.Net (svetainė nebėra, nuoroda nurodo archyvą.org ), ji neveikė norėtų, kad dvejetainis analizavimas pasikliautų vienintelio baito ASCII koduotomis eilutėmis, kurios puikiai veikė, kai transliuojate UTF-8 koduotus duomenis, kol gausite simbolių, kurių ASCII nepalaiko.

Tačiau man pavyko rasti sprendimą skaityti kodą ir jį analizuoti kaip UTF-8.

tinklą, įkeliantį ASP failą , įgyvendinant BytesToString() funkciją iš include_aspuploader.asp į savo kodą, kurį galėjau gauti UTF-8 failų pavadinimus. 


Naudingos nuorodos

1
23 мая '16 в 15:17 2016-05-23 15:17 atsakymą pateikė Lankymart gegužės 23 d., 16 d. 15:17 2016-05-23 15:17

Turėjome panašią problemą žiniatinklio taikomojoje programoje, todėl perskaičiau failo pavadinimą iš HTML <input type="file"> ir įdiegiau jį į URL kodą naujoje HTML <input type="hidden"> . Žinoma, turėjome ištrinti kelią, tokį kaip „C: depresija“, kurį grąžina kai kurios naršyklės.

Žinoma, tai tiesiogiai neatsako į OP klausimą, tačiau tai gali būti sprendimas kitiems.

-1
27 янв. Andrejo I atsakymą pateikė sausio 27 d 2015-01-27 14:54 '15, 14:54, 2015-01-27 14:54

Paprastai koduoju URL (su% xx) failų pavadinimais ir atrodo, kad jis veikia visose naršyklėse. Galbūt norėsite atlikti keletą bandymų.

-2
18 сент. atsakymą pateikė Dario Solera 18 sep. 2008-09-18 18:28 '08 at 18:28 2008-09-18 18:28

Radau sprendimą, kuris veikia visoms mano naršyklėms (t. Y. Visoms naršyklėms, kurias įdiegiau - IE8, FF16, Opera 12, Chrome 22).

Mano sprendimas aprašytas kitoje temoje: „ Java servlet“ atsisiųsti failo specialiųjų simbolių pavadinimą

Mano sprendimas grindžiamas tuo, kaip naršyklės bando skaityti vertę iš filename parametro. Jei filename parametras (pvz., filename*=utf-8''test.xml ) neturi kodavimo, naršyklės tikisi, kad ši vertė bus užkoduota pradiniame naršyklės kode.

Skirtingos naršyklės tikisi puikaus vidinio kodavimo. Paprastai pradinis naršyklės kodavimas yra utf-8 („FireFox“, „Opera“, „Chrome“). Tačiau originalus IE kodavimas yra Win-1250. (Nežinau nieko apie kitas naršykles.)

Todėl, jei vertę į parametrą, kuris yra užkoduotas su utf-8 / win-1250, pagal vartotojo naršyklę, reikia naudoti. Bent jau tai veikia man.

Trumpai tariant, jei turime failą, pavadintą omáčka.xml ,
„FireFox“, „Opera“ ir „Chrome“ atsakysiu į šią antraštę (užkoduota utf-8):

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

ir IE atsakau į šią antraštę (užkoduota laimėjime 1250):

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

„Java“ pavyzdys mano pirmiau minėtame pranešime.

-3
13 нояб. atsakymas pateikiamas sporak Lap 13 2012-11-13 17:43 '12, 17:43, 2012-11-13 17:43