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

535

Aplikasi web yang ingin memaksa sumber daya untuk diunduh daripada secara langsung diberikan di browser Web mengeluarkan Content-Dispositionheader dalam respons HTTP dari formulir:

Content-Disposition: attachment; filename=FILENAME

The filenameparameter 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
Atif Aziz
sumber
Dapat berfungsi untuk Mobile Safari (utf-8 mentah seperti yang disarankan oleh @Martin Ørding-Thomsen), tetapi itu tidak berfungsi untuk GoodReader dari perangkat yang sama. Ada ide?
Thilo
Lihat juga pertanyaan serupa ini
juergen d
1
Jawaban Kornel terbukti sebagai jalan dengan resistensi paling rendah, jika Anda dapat mengatur segmen terakhir dari jalan; pasangan ini dengan Content-Disposition: attachment.
Antti Haapala

Jawaban:

94

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.

Jim
sumber
5
Perhatikan juga bahwa konsep internet (bukan "konsep RFC") telah selesai, dan dokumen terakhir adalah RFC 5987 ( greenbytes.de/tech/webdav/rfc5987.html )
Julian Reschke
11
Terkait dengan ini, saya menemukan bahwa Firefox (versi 4-9 inklusif) rusak jika ada koma (,) dalam nama file, misalnya Content-Disposition: filename="foo, bar.pdf". Hasilnya adalah firefox mengunduh file dengan benar tetapi menjaga .partekstensi (mis foo,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.
catchdave
3
Untuk lebih lanjut tentang perilaku IE, lihat blogs.msdn.com/b/ieinternals/archive/2010/06/07/...
EricLaw
5
@catchdave: Anda lupa "lampiran;" bagian.
Christoffer Hammarström
6
Secara keseluruhan, ini hanyalah jawaban tautan saja dengan 74 upvotes.
Antti Haapala
364

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:

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 langsung di header utf-8 Anda yang dikodekan:

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

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

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

Di ASP.Net saya menggunakan kode berikut:

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

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.

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

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:

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

Martin Ørding-Thomsen
sumber
1
Sudah berfungsi untuk Mobile Safari (utf-8 mentah seperti yang disarankan di atas), tetapi itu tidak berfungsi untuk GoodReader dari perangkat yang sama. Ada ide?
Thilo
1
IE7 dan 8 juga perlu apostrof lolos: .Replace ("'", Uri.HexEscape (' \ ''))
TomZ
1
Menulis karakter UTF-8 secara langsung tampaknya berfungsi untuk versi Firefox, Chrome, dan Opera saat ini. Tidak menguji Safari & IE.
Martin Tournoij
21
Mengapa tidak mengombinasikannya, seperti Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txtdan lewati sniffing browser? Apakah itu akan berhasil?
Dave Van den Eynde
9
Orang-orang baik di fastmail menemukan solusi lain: blog.fastmail.com/2011/06/24/download-non-english-filenames Content-Disposition: attachment; filename = "foo-% c3% a4.html"; filename * = UTF-8''foo-% c3% a4.html Menentukan fileName dua kali (satu kali tanpa awalan UTF-8 dan satu kali dengan) membuatnya berfungsi di IE8-11, Edge, Chrome, Firefox dan Safari ( sepertinya apple fixed safari, jadi itu berfungsi di sana juga sekarang)
wullinkm
169

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:

/real_script.php/fake_filename.doc

Dan jika server Anda mendukung penulisan ulang URL (misalnya mod_rewritedi Apache) maka Anda dapat sepenuhnya menyembunyikan bagian skrip.

Karakter dalam URL harus dalam UTF-8, urlencoded byte-by-byte:

/mot%C3%B6rhead   # motörhead
Kornel
sumber
3
Coba GetAttachment.aspx / fake_filename.doc? Id = 34 (walaupun itu mungkin kekhasan khusus Apache)
Kornel
2
ini adalah solusi fantastis; sangat membantu saya. Terima kasih.
kristopolous
6
Saya menyusuri jalan kelinci dan mencoba beberapa solusi lainnya; mencoba mengendus browser dan versi yang tepat untuk mengatur header dengan benar adalah terlalu banyak mimpi buruk. Chrome salah mengidentifikasi sebagai Safari yang tidak berperilaku sama sekali (jeda pada koma jika tidak dikodekan dengan benar). Simpan sendiri masalahnya, gunakan solusi ini dan alias URL sesuai kebutuhan.
mpen
3
The /:id/:filenameMetode benar-benar sederhana dan karya, terima kasih!
Luca Steeb
2
Seribu kali "Ya". Anda serius akan memenangkan waktu dengan ini. Lebih bahkan - beberapa browser Android akan datar keluar mengabaikan yang Content-Dispositiondan menciptakan nama file yang sangat menarik bukan (mereka akan dihasilkan dari jalan Anda). Jadi satu-satunya solusi untuk menjaga kewarasan seseorang hanya menetapkan Content-Disposition: attachmentdan melewati nama file yang diinginkan sebagai komponen jalur terakhir:
Julik
73

RFC 6266 menjelaskan " Penggunaan Bidang Header Konten-Disposisi di Hypertext Transfer Protocol (HTTP) ". Mengutip dari itu:

6. Pertimbangan Internasionalisasi

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

Dan di bagian contoh mereka :

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

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

Catatan: Agen-agen pengguna yang tidak mendukung encoding RFC 5987 abaikan " filename*" ketika itu terjadi setelah " filename".

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:

  • attwithisofnplain : nama file ISO-8859-1 biasa dengan tanda kutip ganda dan tanpa pengkodean. Ini membutuhkan nama file yang semuanya ISO-8859-1 dan tidak mengandung tanda persen, setidaknya tidak di depan angka hex.
  • attfnboth : dua parameter dalam urutan yang dijelaskan di atas. Seharusnya berfungsi untuk sebagian besar nama file di sebagian besar browser, meskipun IE8 akan menggunakan filenameparameter " ".

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 tubuhmultipart/form-data HTTP , yang diatur oleh RFC 2388 ( bagian 4.4 khususnya) dan konsep HTML 5 .

MvG
sumber
1
Saya mengalami masalah di Safari. Saat mengunduh file dengan nama Rusia menerima karakter yang salah dan tidak dapat dibaca. Solusinya telah membantu. Tetapi kita perlu mengirim tajuk dalam satu baris (!!!).
evtuhovdo
16

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

Atif Aziz
sumber
Perhatikan bahwa satu dapat menyediakan kedua cara pengkodean parameter nama file, dan bahwa mereka tampaknya berfungsi dengan benar dengan browser lama dan browser baru (yang lama MSIE8 dan Safari dalam kasus ini). Periksa attfnboth dalam laporan yang disebutkan oleh @AtifAziz.
Pablo Montilla
11

di asp.net mvc2 saya menggunakan sesuatu seperti ini:

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

Saya kira jika Anda tidak menggunakan mvc (2) Anda hanya bisa menyandikan nama file menggunakan

HttpUtility.UrlPathEncode(fileName)
Elmer
sumber
2
Pengkodean URL untuk pengodean nama file tidak valid, browser seharusnya tidak menguraikan kode tersebut.
SerialSeb
IE 11 pasti tidak mendekode pengkodean url di bidang ini.
pseudocoder
Tapi itu perlu UrlEncoded ketika browser Chrome atau IE, yang lain seperti FF, Safari dan Opera berfungsi dengan baik tanpa pengkodean
Reza
11

Masukkan nama file dalam tanda kutip ganda. Memecahkan masalah bagi saya. Seperti ini:

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

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.

Dmitry Kaigorodov
sumber
3
Sayangnya ini tidak menyelesaikan semua masalah yang dijelaskan dalam jawaban di atas.
Luca Steeb
2
Ini akan memungkinkan Anda untuk mengembalikan nama file dengan spasi, &, %, #dll Jadi itu memecahkan itu.
Don Cheadle
Bagaimana jika nama file berisi tanda kutip ganda (ya ini bisa terjadi), Sebagaimana ditentukan dalam RFC 6266, nama file adalah "string-dikutip", dan seperti yang ditentukan dalam RFC 2616 tanda kutip ganda dalam string-dikutip harus diloloskan dengan backslash.
Christophe Roussy
10

Saya menggunakan potongan kode berikut untuk penyandian (dengan asumsi fileName berisi nama file dan ekstensi file, yaitu: 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
sumber
Benar, itu harus rawurlencodedalam PHP setidaknya untuk filename*=header disposisi sejak value-charsdigunakan dalam ext-valueRFC 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 dihapus
Brett Zamir
9

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

IE 9 Tidak diperbaiki
IE 9 Tetap

martinoss
sumber
5

Saya menguji kode berikut di semua browser utama, termasuk Penjelajah yang lebih lama (melalui mode kompatibilitas), dan bekerja dengan baik di mana-mana:

$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
sumber
5

Saya berakhir dengan kode berikut dalam skrip "download.php" saya (berdasarkan blogpost ini dan beberapa test case ).

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

apurkrt
sumber
... tetapi panjang nama file maks yang dapat ditransfer juga tergantung pada klien. Baru tahu bahwa paling banyak [89 smiles😁] .pdf nama file didapat melalui MSIE11. Di Firefox37, paling banyak [111x 😁] .pdf. Chrome41 memotong nama file pada senyum ke-110. Menariknya, sufiks ditransfer ok.
apurkrt
5

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

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
sumber
1
Lebih baik digunakan 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"
gdibble
4

Dalam PHP ini melakukannya untuk saya (dengan asumsi nama file dikodekan 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 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.

Gustav
sumber
3
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana ia menjawab pertanyaan akan secara signifikan meningkatkan nilai jangka panjangnya. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan.
Toby Speight
2
Whoa, tidak ada jawaban kode-saja di atas yang downvoted atau dikritik seperti itu. Saya juga sudah menemukan jawabannya mengapa sudah dijawab dengan cukup baik: IE tidak mengartikan nama file * = utf-8 tetapi membutuhkan versi nama file ISO8859-1, yang ditawarkan skrip ini. Hanya ingin memberi malas kode sederhana yang berfungsi untuk PHP.
Gustav
Saya pikir ini diturunkan karena pertanyaannya bukan bahasa spesifik tetapi tentang apa RFC untuk menempel ketika menerapkan pengkodean header. Namun terima kasih, untuk jawaban ini, untuk PHP, kode ini membuat kesengsaraan saya hilang.
j4k3
Terima kasih. Jawaban ini mungkin tidak benar-benar menjawab pertanyaan, tapi itu persis apa yang saya cari dan membantu saya menyelesaikan masalah dengan Python.
Lyndsy Simon
1
Saya cukup yakin kode ini dapat digunakan sebagai vektor serangan jika pengguna dapat mengontrol nama file.
Antti Haapala
3

Hanya pembaruan sejak saya mencoba semua hal ini hari ini sebagai tanggapan terhadap masalah pelanggan

  • Dengan pengecualian Safari yang dikonfigurasikan untuk bahasa Jepang, semua browser yang diuji pelanggan kami berfungsi paling baik dengan nama file = text.pdf - di mana teks adalah nilai pelanggan yang diserialisasi oleh ASP.Net/IIS dalam utf-8 tanpa pengkodean url. Untuk beberapa alasan, Safari yang dikonfigurasikan untuk Bahasa Inggris akan menerima dan menyimpan file dengan benar dengan nama Jepang utf-8 tetapi browser yang sama yang dikonfigurasi untuk bahasa Jepang akan menyimpan file dengan karakter utf-8 yang tidak diinterpretasikan. Semua browser lain yang diuji tampaknya berfungsi dengan baik / baik (terlepas dari konfigurasi bahasa) dengan nama file utf-8 yang dikodekan tanpa pengkodean url.
  • Saya tidak dapat menemukan satu pun browser yang mengimplementasikan Rfc5987 / 8187 sama sekali . Saya diuji dengan Chrome terbaru, Firefox build plus IE 11 dan Edge. Saya mencoba mengatur header dengan hanya nama file * = utf-8''texturlencoded.pdf, mengaturnya dengan kedua nama file = text.pdf; filename * = utf-8''texturlencoded.pdf. Tidak satu pun fitur Rfc5987 / 8187 yang tampaknya diproses dengan benar di salah satu di atas.
pengguna1664043
sumber
Ini adalah pembaruan yang bagus. Bisakah Anda menguraikan tes spesifik yang Anda coba?
Brad
3

Kerangka kerja PHP Symfony 4 ada $filenameFallbackdi HeaderUtils::makeDisposition. Anda dapat melihat ke dalam fungsi ini untuk perincian - mirip dengan jawaban di atas.

Contoh penggunaan:

$filenameFallback = preg_replace('#^.*\.#', md5($filename) . '.', $filename);
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename, $filenameFallback);
$response->headers->set('Content-Disposition', $disposition);
luchaninov
sumber
1

Solusi ASP Klasik

Sebagian besar peramban modern mendukung lewat Filenameseperti UTF-8sekarang 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.

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

Kredit digunakan untuk Upload File ASP Murni dengan menerapkan BytesToString()fungsi dari include_aspuploader.aspdalam kode saya sendiri, saya dapat membuat UTF-8nama file berfungsi.


Tautan yang Berguna

Lankymart
sumber
-1

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.

Andrei I
sumber
1
Masalah yang sama sekali berbeda. Pertanyaannya adalah tentang mengunduh , balasan Anda adalah tentang mengunggah .
Oskar Berggren
-3

Saya biasanya URL-encode (dengan% xx) nama file, dan tampaknya berfungsi di semua browser. Anda mungkin ingin melakukan beberapa tes.

Dario Solera
sumber
10
Saya melakukan beberapa tes dan tidak bekerja seperti itu di semua browser, jadi pertanyaannya. :)
Atif Aziz