Jak zakodować parametr nazwy nagłówka Content-Disposition w HTTP?

533

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 filenameparametr 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
Atif Aziz
źródło
Sprawił, że działa w Mobile Safari (raw utf-8, jak sugeruje @Martin Ørding-Thomsen), ale to nie działa dla GoodReadera z tego samego urządzenia. Jakieś pomysły?
Thilo,
Zobacz także podobne pytanie
juergen d
1
Odpowiedź Kornela okazała się ścieżką najmniejszego oporu, jeśli potrafisz ustawić ostatni odcinek ścieżki; połącz to z Content-Disposition: attachment.
Antti Haapala

Odpowiedzi:

94

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.

Jim
źródło
5
Należy również pamiętać, że wersja internetowa (nie „wersja robocza RFC”) została ukończona, a ostatecznym dokumentem jest RFC 5987 ( greenbytes.de/tech/webdav/rfc5987.html )
Julian Reschke
11
W związku z tym odkryłem, że Firefox (wersje 4-9 włącznie) pęka, jeśli w nazwie pliku występuje przecinek (,), np Content-Disposition: filename="foo, bar.pdf". W rezultacie firefox poprawnie pobiera plik, ale zachowuje .partrozszerzenie (np foo,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.
catchdave
3
Aby uzyskać więcej informacji na temat zachowania IE, zobacz blogs.msdn.com/b/ieinternals/archive/2010/06/07/…
EricLaw
5
@catchdave: Zapomniałeś „załącznika”; część.
Christoffer Hammarström,
6
Podsumowując, jest to odpowiedź tylko z linkiem z 74 głosami pozytywnymi.
Antti Haapala,
364

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ę:

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

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:

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

IE8 i starsze też go nie obsługują i musisz użyć standardu IE kodowania utf-8, zakodowanego procentowo:

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

W ASP.Net używam następującego kodu:

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.Browser.Browser == "Safari")
    contentDisposition = "attachment; filename=" + fileName;
else
    contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

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.

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

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ą:

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: 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.

Martin Ørding-Thomsen
źródło
1
Sprawił, że działał na Mobile Safari (raw utf-8 jak zasugerowano powyżej), ale to nie działa dla GoodReadera z tego samego urządzenia. Jakieś pomysły?
Thilo,
1
IE7 i 8 również wymagają ucieczki apostrofów: .Replace („”, Uri.HexEscape ('\' '))
TomZ
1
Wydaje się, że bezpośrednie pisanie znaków UTF-8 działa w obecnych wersjach Firefox, Chrome i Opera. Nie testowałem Safari i IE.
Martin Tournoij
20
Dlaczego ich nie połączyć, jak Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txti pominąć wąchanie przeglądarki? Czy to zadziała?
Dave Van den Eynde
9
Uprzejmi ludzie w fastmail znaleźli inne obejście: blog.fastmail.com/2011/06/24/download-non-english-filenames Content-Disposition: załącznik; nazwa pliku = "foo-% c3% a4.html"; nazwa pliku * = UTF-8''foo-% c3% a4.html Podanie nazwy pliku dwa razy (jeden raz bez prefiksu UTF-8 i jeden raz z) powoduje, że działa on w IE8-11, Edge, Chrome, Firefox i Safari ( wygląda na naprawione jabłko, więc teraz też tam działa)
wullinkm,
169

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:

/real_script.php/fake_filename.doc

A jeśli twój serwer obsługuje przepisywanie adresów URL (np. mod_rewriteW Apache), możesz w pełni ukryć część skryptu.

Znaki w adresach URL powinny mieć postać UTF-8, urlencoded byte by by byte:

/mot%C3%B6rhead   # motörhead
Kornel
źródło
3
Spróbuj GetAttachment.aspx / fake_filename.doc? Id = 34 (chociaż może to być tylko dziwactwo Apache)
Kornel
2
to fantastyczne rozwiązanie; bardzo mi pomogło. dzięki.
kristopolous
6
Zszedłem szlakiem królików i wypróbowałem inne rozwiązania; próba wykrycia prawidłowej przeglądarki i wersji w celu prawidłowego ustawienia nagłówków jest zbyt wielkim koszmarem. Chrome niepoprawnie identyfikuje się jako Safari, która w ogóle nie zachowuje się tak samo (przerywa przecinki, jeśli nie jest poprawnie zakodowana). Zaoszczędź sobie kłopotów, skorzystaj z tego rozwiązania i w razie potrzeby użyj aliasu adresu URL.
mpen
3
/:id/:filenameMetoda jest bardzo prosta i prace, dziękuję!
Luca Steeb,
2
Tysiąc razy „Tak”. Poważnie zyskasz dzięki temu czas. Więcej nawet - niektóre Android przeglądarek płaskim się ignorować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 ustawienie Content-Disposition: attachmenti przekazanie żądanej nazwy pliku jako ostatniego komponentu ścieżki:
Julik
73

RFC 6266 opisuje „ Wykorzystanie pola nagłówka dysponowania zawartością w protokole przesyłania hipertekstu (HTTP) ”. Cytując z tego:

6. Zagadnienia dotyczące internacjonalizacji

Parametr „ filename*” ( sekcja 4.3 ), wykorzystujący kodowanie zdefiniowane w [ RFC5987 ], pozwala serwerowi przesyłać znaki poza zestawem znaków ISO-8859-1, a także opcjonalnie określać używany język.

I w sekcji przykładów :

Ten przykład jest taki sam jak powyższy, ale dodanie parametru „nazwa pliku” w celu zapewnienia zgodności z klientami użytkownika nie implementującymi RFC 5987 :

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

Uwaga: te programy użytkownika, które nie obsługują kodowania RFC 5987, ignorują „ filename*”, gdy pojawia się po „ filename”.

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ą:

  • attwithisofnplain : zwykła nazwa pliku ISO-8859-1 z podwójnymi cudzysłowami i bez kodowania. Wymaga to nazwy pliku, która jest w całości ISO-8859-1 i nie zawiera znaków procentu, przynajmniej nie przed cyframi szesnastkowymi.
  • attfnboth : dwa parametry w kolejności opisanej powyżej. Powinien działać dla większości nazw plików w większości przeglądarek, chociaż IE8 użyje filenameparametru „ ”.

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ścimultipart/form-data HTTP , która jest regulowana przez RFC 2388 ( w szczególności sekcja 4.4 ) i wersję roboczą HTML 5 .

MvG
źródło
1
Miałem kłopoty w Safari. Podczas pobierania plików z rosyjskimi nazwami otrzymywały błędne i nieczytelne znaki. Rozwiązanie pomogło. Ale musimy wysłać nagłówek w jednym wierszu (!!!).
evtuhovdo
16

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

Atif Aziz
źródło
Zauważ, że można podać oba sposoby kodowania parametru nazwy pliku i wydaje się, że działają one poprawnie ze starymi przeglądarkami i nowymi przeglądarkami (w tym przypadku starymi są MSIE8 i Safari). Sprawdź attfnboth w raporcie wspomnianym przez @AtifAziz.
Pablo Montilla,
11

w asp.net mvc2 używam czegoś takiego:

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

Myślę, że jeśli nie używasz mvc (2), możesz po prostu zakodować nazwę pliku za pomocą

HttpUtility.UrlPathEncode(fileName)
Elmer
źródło
2
Kodowanie adresu URL do kodowania nazwy pliku jest nieprawidłowe, przeglądarki nie powinny go dekodować.
SerialSeb
IE 11 zdecydowanie nie dekoduje kodowania adresu URL w tym polu.
pseudokoder
Ale trzeba było UrlEncoded, gdy przeglądarka jest Chrome lub IE, inne takie jak FF, Safari i Opera działają dobrze bez kodowania
Reza
10

Używam następujące fragmenty kodu do kodowania (zakładając fileName zawiera nazwę pliku i rozszerzenie pliku, a mianowicie: test.txt):


PHP:

if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
     header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $fileName ) . '"' );
}
else
{
     header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $fileName ) );
}

Jawa:

fileName = request.getHeader ( "user-agent" ).contains ( "MSIE" ) ? URLEncoder.encode ( fileName, "utf-8") : MimeUtility.encodeWord ( fileName );
response.setHeader ( "Content-disposition", "attachment; filename=\"" + fileName + "\"");
Vasilen Donchev
źródło
Tak, powinien być rawurlencodew PHP przynajmniej dla filename*=nagłówka dyspozycji od czasu value-charsużycia w ext-valueRFC 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ąć
Brett Zamir
10

Umieść nazwę pliku w podwójnym cudzysłowie. Rozwiązałem problem dla mnie. Lubię to:

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

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.

Dmitrij Kaigorodov
źródło
3
To niestety nie rozwiązuje wszystkich problemów wyjaśnionych w powyższych odpowiedziach.
Luca Steeb,
2
Pozwoli to na powrót na nazwę pliku ze spacjami, &, %, #itd. Więc to, że rozwiązuje.
Don Cheadle
Co jeśli nazwa pliku zawiera podwójne cudzysłowy (tak może się zdarzyć), jak określono w RFC 6266, nazwa pliku to „ciąg cudzysłowu”, a jak podano w RFC 2616, podwójne cudzysłowy w ciągu ciągu cudzysłowu powinny być poprzedzone odwrotnym ukośnikiem.
Christophe Roussy,
9

W ASP.NET Web API, koduję adres URL pliku:

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;
    }
}

IE 9 Nie naprawiono
IE 9 Naprawiono

martinoss
źródło
5

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:

$filename = $_GET['file']; //this string from $_GET is already decoded
if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE"))
  $filename = rawurlencode($filename);
header('Content-Disposition: attachment; filename="'.$filename.'"');
Stano
źródło
5

Skończyłem z następującym kodem w moim skrypcie „download.php” (na podstawie tego postu na blogu i tych przypadków testowych ).

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

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.

apurkrt
źródło
... ale maksymalna możliwa do przeniesienia długość nazwy pliku zależy również od klienta. Właśnie dowiedziałem się, że co najwyżej [89 uśmiechów] .pdf nazwa pliku przechodzi przez MSIE11. W przeglądarce Firefox37 jest to co najwyżej [111x 😁] .pdf. Chrome41 obcina nazwę pliku przy 110. uśmiechu. Co ciekawe, przyrostek został przeniesiony ok.
apurkrt
5

Jeśli używasz backendu nodejs, możesz użyć następującego kodu, który tutaj znalazłem

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" 
             + encodeRFC5987ValueChars(fileName);

function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            // so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}
Emanuele Spatola
źródło
1
Lepszy w użyciu 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”
gdibble
4

W PHP zrobiło to dla mnie (zakładając, że nazwa pliku jest zakodowana w UTF8):

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

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 iconvzamiast tego.

Gustav
źródło
3
Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak odpowiada na pytanie, znacznie poprawiłoby jego długoterminową wartość. Proszę edytować swoje odpowiedzi, aby dodać trochę wyjaśnień.
Toby Speight
2
Whoa, żadna z powyższych odpowiedzi tylko na kod nie była tak krytykowana ani krytykowana. Dowiedziałem się również, dlaczego odpowiedź była wystarczająco dobrze: IE nie interpretuje nazwy pliku * = utf-8, ale potrzebuje wersji pliku ISO8859-1, którą oferuje ten skrypt. Chciałem tylko dać leniwemu działający prosty kod dla PHP.
Gustaw
Myślę, że zostało to zanegowane, ponieważ pytanie nie jest specyficzne dla języka, ale o tym, do jakich RFC należy się trzymać przy implementacji kodowania nagłówka. Dzięki za tę odpowiedź, dla PHP, ten kod sprawił, że moje nieszczęścia zniknęły.
j4k3
Dziękuję Ci. Ta odpowiedź mogła nie udzielić ścisłej odpowiedzi na pytanie, ale dokładnie tego szukałam i pomogła mi rozwiązać problem w Pythonie.
Lyndsy Simon
1
Jestem pewien, że ten kod może zostać użyty jako wektor ataku, jeśli użytkownik może kontrolować nazwę pliku.
Antti Haapala,
3

To tylko aktualizacja, odkąd próbowałem dzisiaj tego wszystkiego w odpowiedzi na problem klienta

  • Z wyjątkiem przeglądarki Safari skonfigurowanej dla języka japońskiego, wszystkie testowane przez nas przeglądarki najlepiej działały z nazwą pliku = tekst.pdf - gdzie tekst jest wartością klienta zserializowaną przez ASP.Net/IIS w utf-8 bez kodowania adresu URL. Z jakiegoś powodu Safari skonfigurowane na angielski akceptuje i poprawnie zapisuje plik z japońską nazwą utf-8, ale ta sama przeglądarka skonfigurowana dla japońskiego zapisuje plik z niezinterpretowanymi znakami utf-8. Wszystkie pozostałe przetestowane przeglądarki działały najlepiej / dobrze (niezależnie od konfiguracji języka) z nazwą pliku utf-8 zakodowaną bez kodowania URL.
  • Nie mogłem znaleźć jednego przeglądarkę wykonawczych Rfc5987 / 8187 w ogóle . Testowałem z najnowszymi wersjami Chrome, Firefox oraz IE 11 i Edge. Próbowałem ustawić nagłówek tylko z nazwą pliku * = utf-8''texturlencoded.pdf, ustawiając go zarówno z nazwą pliku = tekst.pdf; nazwa pliku * = utf-8''texturlencoded.pdf. Wydaje się, że żadna z funkcji Rfc5987 / 8187 nie jest poprawnie przetwarzana w żadnym z powyższych.
użytkownik1664043
źródło
To dobra aktualizacja. Czy możesz opracować szczegółowe testy, które próbowałeś?
Brad
3

PHP framework Symfony 4 ma $filenameFallbackw HeaderUtils::makeDisposition. Możesz zajrzeć do tej funkcji, aby poznać szczegóły - jest ona podobna do powyższych odpowiedzi.

Przykład użycia:

$filenameFallback = preg_replace('#^.*\.#', md5($filename) . '.', $filename);
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename, $filenameFallback);
$response->headers->set('Content-Disposition', $disposition);
Luchaninov
źródło
1

Klasyczne rozwiązanie ASP

Większość współczesnych przeglądarek obsługuje przekazywanie Filenamejak UTF-8teraz, 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.

Public Function BytesToString(bytes)    'UTF-8..
  Dim bslen
  Dim i, k , N 
  Dim b , count 
  Dim str

  bslen = LenB(bytes)
  str=""

  i = 0
  Do While i < bslen
    b = AscB(MidB(bytes,i+1,1))

    If (b And &HFC) = &HFC Then
      count = 6
      N = b And &H1
    ElseIf (b And &HF8) = &HF8 Then
      count = 5
      N = b And &H3
    ElseIf (b And &HF0) = &HF0 Then
      count = 4
      N = b And &H7
    ElseIf (b And &HE0) = &HE0 Then
      count = 3
      N = b And &HF
    ElseIf (b And &HC0) = &HC0 Then
      count = 2
      N = b And &H1F
    Else
      count = 1
      str = str & Chr(b)
    End If

    If i + count - 1 > bslen Then
      str = str&"?"
      Exit Do
    End If

    If count>1 then
      For k = 1 To count - 1
        b = AscB(MidB(bytes,i+k+1,1))
        N = N * &H40 + (b And &H3F)
      Next
      str = str & ChrW(N)
    End If
    i = i + count
  Loop

  BytesToString = str
End Function

Zasługa Czysta ASP upload plików poprzez wdrożenie BytesToString()funkcji z include_aspuploader.aspmoim własnym kodem udało mi się dostać UTF-8nazw roboczych.


Przydatne linki

Lankymart
źródło
-1

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.

Andrei I
źródło
1
Zupełnie inny problem. Pytanie dotyczy pobierania , twoja odpowiedź dotyczy przesyłania .
Oskar Berggren,
-3

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.

Dario Solera
źródło
10
Testowałem już w kilku i nie działa to tak we wszystkich przeglądarkach, stąd pytanie. :)
Atif Aziz