Aplikacje internetowe, które chcą wymusić pobranie zasobu zamiast bezpośredniego renderowania w przeglądarce internetowej, powodują problemContent-Disposition
nagłówek w odpowiedzi HTTP formularza:
Content-Disposition: attachment; filename=FILENAME
Ten filename
parametr może służyć do sugerowania nazwy pliku, do którego zasób jest pobierany przez przeglądarkę. Jednak RFC 2183 (Content-Disposition) stwierdza w sekcji 2.3 (Parametr nazwy pliku), że nazwa pliku może zawierać tylko znaki US-ASCII:
Obecna gramatyka [RFC 2045] ogranicza wartości parametrów (a zatem nazwy plików Content-Disposition) do US-ASCII. Zdajemy sobie sprawę z ogromnej potrzeby dopuszczania dowolnych zestawów znaków w nazwach plików, ale zdefiniowanie niezbędnych mechanizmów wykracza poza zakres tego dokumentu.
Istnieją jednak dowody empiryczne, że większość popularnych przeglądarek internetowych wydaje się obecnie zezwalać na znaki spoza US-ASCII (z braku standardu) nie zgadzają się co do schematu kodowania i specyfikacji zestawu znaków nazwy pliku. Pytanie brzmi, jakie są różne schematy i kodowania stosowane w popularnych przeglądarkach, jeśli nazwa pliku „naïvefile” (bez cudzysłowów i gdzie trzecia litera to U + 00EF) musiała zostać zakodowana w nagłówku Content-Disposition?
Do celów tego pytania popularne przeglądarki to:
- Firefox
- Internet Explorer
- Safari
- Google Chrome
- Opera
źródło
Content-Disposition: attachment
.Odpowiedzi:
Dyskusja na ten temat, w tym łącza do testowania przeglądarki i kompatybilności wstecznej, w proponowanym RFC 5987 „Zestaw znaków i kodowanie języka dla parametrów pola nagłówka protokołu przesyłania hipertekstu (HTTP)”.
RFC 2183 wskazuje, że takie nagłówki powinny być kodowane zgodnie z RFC 2184 , który został przestarzały w RFC 2231 , objęty powyższym projektem RFC.
źródło
Content-Disposition: filename="foo, bar.pdf"
. W rezultacie firefox poprawnie pobiera plik, ale zachowuje.part
rozszerzenie (npfoo,bar.pdf-1.part
.). Wtedy oczywiście plik nie otworzy się poprawnie, ponieważ aplikacja nie jest powiązana.part
. Inne znaki ASCII wydają się działać OK.Wiem, że to stary post, ale nadal jest bardzo istotny. Przekonałem się, że współczesne przeglądarki obsługują rfc5987, który umożliwia kodowanie utf-8, kodowane procentowo (kodowane w adresie URL). Następnie plik Naïve file.txt staje się:
Safari (5) nie obsługuje tego. Zamiast tego powinieneś użyć standardu Safari, aby zapisać nazwę pliku bezpośrednio w nagłówku zakodowanym w utf-8:
IE8 i starsze też go nie obsługują i musisz użyć standardu IE kodowania utf-8, zakodowanego procentowo:
W ASP.Net używam następującego kodu:
Testowałem powyższe przy użyciu IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Aktualizacja z listopada 2013 r .:
Oto kod, którego obecnie używam. Nadal muszę wspierać IE8, więc nie mogę pozbyć się pierwszej części. Okazuje się, że przeglądarki na Androidzie używają wbudowanego menedżera pobierania Androida i nie mogą w niezawodny sposób parsować nazw plików w standardowy sposób.
Powyższe testy zostały teraz przetestowane w IE7-11, Chrome 32, Opera 12, FF25, Safari 6, przy użyciu tej nazwy pliku do pobrania: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýý½!!! # ¤% & () = `@ £ $ {{]] + ´¨ ^ ~ '-_,;. txt
W IE7 działa dla niektórych znaków, ale nie dla wszystkich. Ale kogo dzisiaj obchodzi IE7?
Jest to funkcja, której używam do generowania bezpiecznych nazw plików dla Androida. Pamiętaj, że nie wiem, które znaki są obsługiwane na Androidzie, ale przetestowałem na pewno, czy działają:
@TomZ: Testowałem w IE7 i IE8 i okazało się, że nie musiałem uciekać od apostrofu ('). Czy masz przykład, w którym zawodzi?
@Dave Van den Eynde: Łączenie dwóch nazw plików w jednym wierszu zgodnie z RFC6266 działa z wyjątkiem Androida i IE7 + 8, a ja zaktualizowałem kod, aby to odzwierciedlić. Dziękuję za sugestię.
@Thilo: Nie mam pojęcia o GoodReaderze ani żadnej innej przeglądarce. Możesz mieć trochę szczęścia, korzystając z systemu Android.
@Alex Zhukovskiy: Nie wiem dlaczego, ale jak omówiono w Connect , wydaje się, że nie działa to zbyt dobrze.
źródło
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
i pominąć wąchanie przeglądarki? Czy to zadziała?Nie ma interoperacyjnego sposobu kodowania nazw spoza ASCII
Content-Disposition
. Kompatybilność z przeglądarkami to bałagan .Teoretycznie poprawna składnia do użycia w UTF-8
Content-Disposition
jest bardzo dziwne:filename*=UTF-8''foo%c3%a4
(tak, to gwiazdkę, a nie cytaty z wyjątkiem pustego pojedynczy cudzysłów w środku)Ten nagłówek jest trochę niezupełnie standardowy ( specyfikacja HTTP / 1.1 potwierdza jego istnienie , ale nie wymaga obsługi przez klientów).
Istnieje prosta i bardzo solidna alternatywa: użyj adresu URL zawierającego żądaną nazwę pliku .
Kiedy nazwa po ostatnim ukośniku jest tym, czego potrzebujesz, nie potrzebujesz żadnych dodatkowych nagłówków!
Ta sztuczka działa:
A jeśli twój serwer obsługuje przepisywanie adresów URL (np.
mod_rewrite
W Apache), możesz w pełni ukryć część skryptu.Znaki w adresach URL powinny mieć postać UTF-8, urlencoded byte by by byte:
źródło
/:id/:filename
Metoda jest bardzo prosta i prace, dziękuję!Content-Disposition
i stworzyć bardzo ciekawe nazwy plików zamiast (będą generowane z trasy). Tak więc jedynym rozwiązaniem dla zachowania zdrowia psychicznego jest ustawienieContent-Disposition: attachment
i przekazanie żądanej nazwy pliku jako ostatniego komponentu ścieżki:RFC 6266 opisuje „ Wykorzystanie pola nagłówka dysponowania zawartością w protokole przesyłania hipertekstu (HTTP) ”. Cytując z tego:
I w sekcji przykładów :
W załączniku D znajduje się również długa lista sugestii dotyczących zwiększenia interoperacyjności. Wskazuje także na stronę porównującą implementacje . Obecne testy kompleksowe odpowiednie dla popularnych nazw plików obejmują:
filename
parametru „ ”.Ten RFC 5987 z kolei odwołuje się do RFC 2231 , który opisuje rzeczywisty format. 2231 dotyczy głównie poczty, a 5987 mówi nam, które części mogą być użyte również w nagłówkach HTTP. Nie myl tego z nagłówkami MIME używanymi w treści
multipart/form-data
HTTP , która jest regulowana przez RFC 2388 ( w szczególności sekcja 4.4 ) i wersję roboczą HTML 5 .źródło
Poniższy dokument powiązany z projektem RFC wspomnianym przez Jima w jego odpowiedzi dodatkowo odnosi się do pytania i na pewno warto tutaj zwrócić uwagę:
Przypadki testowe dla nagłówka HTTP Content-Disposition i kodowania RFC 2231/2047
źródło
w asp.net mvc2 używam czegoś takiego:
Myślę, że jeśli nie używasz mvc (2), możesz po prostu zakodować nazwę pliku za pomocą
źródło
Używam następujące fragmenty kodu do kodowania (zakładając fileName zawiera nazwę pliku i rozszerzenie pliku, a mianowicie: test.txt):
PHP:
Jawa:
źródło
rawurlencode
w PHP przynajmniej dlafilename*=
nagłówka dyspozycji od czasuvalue-chars
użycia wext-value
RFC 6266-> RFC 5987 (patrz tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section -3.2.1 ) nie pozwala na spację bez procentowego ucieczki (filename=
z drugiej strony wydaje się, że może pozwolić na spację bez ucieczki w ogóle, chociaż powinno tu być tylko ASCII). Nie jest konieczne kodowanie z pełną surowością kodu rawurlencode, więc można uniknąćUmieść nazwę pliku w podwójnym cudzysłowie. Rozwiązałem problem dla mnie. Lubię to:
http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
Przetestowałem wiele opcji. Przeglądarki nie obsługują specyfikacji i działają inaczej, uważam, że podwójne cudzysłowy to najlepsza opcja.
źródło
&
,%
,#
itd. Więc to, że rozwiązuje.W ASP.NET Web API, koduję adres URL pliku:
źródło
Testowałem następujący kod we wszystkich głównych przeglądarkach, w tym starszych odkrywcach (poprzez tryb zgodności) i działa dobrze wszędzie:
źródło
Skończyłem z następującym kodem w moim skrypcie „download.php” (na podstawie tego postu na blogu i tych przypadków testowych ).
Używa standardowej metody nazwa_pliku = „...”, o ile używane są tylko znaki iso-latin1 i „bezpieczne”; jeśli nie, dodaje nazwę pliku * = UTF-8 '' zakodowaną w url. Zgodnie z tym konkretnym przypadkiem testowym powinien on działać od wersji MSIE9 w górę, a także w najnowszych wersjach FF, Chrome i Safari; w niższej wersji MSIE powinien oferować nazwę pliku zawierającą wersję pliku ISO8859-1, z podkreśleniami na znakach spoza tego kodowania.
Uwaga końcowa: maks. Rozmiar każdego pola nagłówka wynosi 8190 bajtów w Apache. UTF-8 może mieć do czterech bajtów na znak; po rawurlencode wynosi x3 = 12 bajtów na jeden znak. Całkiem nieefektywne, ale teoretycznie powinno być możliwe, aby w nazwie pliku było ponad 600 „uśmiechów”% F0% 9F% 98% 81.
źródło
Jeśli używasz backendu nodejs, możesz użyć następującego kodu, który tutaj znalazłem
źródło
encodeURI(str)
. Jako przykład z datami w nazwie pliku: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”W PHP zrobiło to dla mnie (zakładając, że nazwa pliku jest zakodowana w UTF8):
Testowane przeciwko IE8-11, Firefox i Chrome.
Jeśli przeglądarka może zinterpretować nazwę pliku * = utf-8 , użyje wersji pliku UTF8, w przeciwnym razie użyje zdekodowanej nazwy pliku. Jeśli nazwa pliku zawiera znaki, których nie można przedstawić w ISO-8859-1, warto rozważyć użycie
iconv
zamiast tego.źródło
To tylko aktualizacja, odkąd próbowałem dzisiaj tego wszystkiego w odpowiedzi na problem klienta
źródło
PHP framework Symfony 4 ma
$filenameFallback
wHeaderUtils::makeDisposition
. Możesz zajrzeć do tej funkcji, aby poznać szczegóły - jest ona podobna do powyższych odpowiedzi.Przykład użycia:
źródło
Klasyczne rozwiązanie ASP
Większość współczesnych przeglądarek obsługuje przekazywanie
Filename
jakUTF-8
teraz, ale tak jak w przypadku używanego przeze mnie rozwiązania do przesyłania plików, które było oparte na FreeASPUpload.Net (strona już nie istnieje, wskazuje linki do archive.org ), to nie działałoby jako parsowanie plik binarny polegał na odczycie ciągów jednobajtowych zakodowanych w ASCII, co działało dobrze, gdy przekazałeś dane zakodowane w UTF-8, dopóki nie dojdziesz do znaków, które ASCII nie obsługuje.Byłem jednak w stanie znaleźć rozwiązanie, aby kod odczytywał i analizował plik binarny jako UTF-8.
Zasługa Czysta ASP upload plików poprzez wdrożenie
BytesToString()
funkcji zinclude_aspuploader.asp
moim własnym kodem udało mi się dostaćUTF-8
nazw roboczych.Przydatne linki
Multipart / form-data i UTF-8 w aplikacji ASP Classic
Różnice w formatach Unicode, UTF, ASCII, ANSI
źródło
Wystąpił podobny problem w aplikacji internetowej i ostatecznie przeczytaliśmy nazwę pliku z kodu HTML
<input type="file">
i ustawiliśmy go w postaci zakodowanej w adresie URL w nowym formacie HTML<input type="hidden">
. Oczywiście musieliśmy usunąć ścieżkę typu „C: \ fakepath \” zwracaną przez niektóre przeglądarki.Oczywiście nie odpowiada to bezpośrednio na pytanie PO, ale może być rozwiązaniem dla innych.
źródło
Zwykle koduję adresy URL (z% xx) nazw plików i wydaje się, że działają one we wszystkich przeglądarkach. W każdym razie możesz chcieć zrobić kilka testów.
źródło