Os aplicativos da Web que desejam forçar o download de um recurso, em vez de serem renderizados diretamente em um navegador da Web, emitem um Content-Disposition
cabeçalho na resposta HTTP do formulário:
Content-Disposition: attachment; filename=FILENAME
O filename
parâmetro pode ser usado para sugerir um nome para o arquivo no qual o recurso é baixado pelo navegador. A RFC 2183 (Content-Disposition), no entanto, afirma na seção 2.3 (O parâmetro FileName) que o nome do arquivo pode usar apenas caracteres US-ASCII:
A gramática atual [RFC 2045] restringe os valores dos parâmetros (e, portanto, os nomes dos arquivos Content-Disposition) para US-ASCII. Reconhecemos a grande conveniência de permitir conjuntos de caracteres arbitrários nos nomes de arquivos, mas está além do escopo deste documento definir os mecanismos necessários.
Há evidências empíricas, no entanto, de que os navegadores da Web mais populares hoje em dia parecem permitir caracteres não-USCI ASCII ainda (por falta de um padrão) discordam do esquema de codificação e da especificação do conjunto de caracteres do nome do arquivo. A questão é, então, quais são os vários esquemas e codificações empregados pelos navegadores populares se o nome do arquivo "naïvefile" (sem aspas e onde a terceira letra é U + 00EF) precisou ser codificado no cabeçalho Disposição de Conteúdo?
Para os fins desta pergunta, os navegadores populares são:
- Raposa de fogo
- Internet Explorer
- Safári
- Google Chrome
- Ópera
fonte
Content-Disposition: attachment
.Respostas:
Há discussões sobre isso, incluindo links para teste de navegador e compatibilidade com versões anteriores, na RFC 5987 proposta , "Conjunto de caracteres e codificação de idioma para parâmetros de campo de cabeçalho HTTP (Hypertext Transfer Protocol)".
A RFC 2183 indica que esses cabeçalhos devem ser codificados de acordo com a RFC 2184 , que foi obsoleta pela RFC 2231 , coberta pelo rascunho da RFC acima.
fonte
Content-Disposition: filename="foo, bar.pdf"
. O resultado é que o Firefox baixa o arquivo corretamente, mas mantém a.part
extensão (por exemplofoo,bar.pdf-1.part
). Então, é claro que o arquivo não abrirá corretamente porque o aplicativo não está associado.part
. Outros caracteres ASCII parecem funcionar bem.Eu sei que este é um post antigo, mas ainda é muito relevante. Eu descobri que os navegadores modernos oferecem suporte ao rfc5987, que permite a codificação utf-8, porcentagem codificada (codificada por url). Então o arquivo Naïve.txt se torna:
O Safari (5) não suporta isso. Em vez disso, você deve usar o padrão Safari para escrever o nome do arquivo diretamente no cabeçalho codificado utf-8:
O IE8 e versões anteriores também não são compatíveis e você precisa usar o padrão IE de codificação utf-8, porcentagem codificada:
No ASP.Net, uso o seguinte código:
Testei o acima usando IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Atualização em novembro de 2013:
Aqui está o código que atualmente uso. Eu ainda tenho que dar suporte ao IE8, então não consigo me livrar da primeira parte. Acontece que os navegadores no Android usam o gerenciador de downloads interno do Android e não podem analisar nomes de arquivos de maneira confiável da maneira padrão.
Os itens acima agora foram testados no IE7-11, Chrome 32, Opera 12, FF25, Safari 6, usando este nome de arquivo para download: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúúññ½§! ^ ~ '-_,;. txt
No IE7, ele funciona para alguns caracteres, mas não para todos. Mas quem se importa com o IE7 hoje em dia?
Essa é a função que eu uso para gerar nomes de arquivos seguros para o Android. Observe que não sei quais caracteres são suportados no Android, mas testei que eles funcionam com certeza:
@TomZ: Eu testei no IE7 e IE8 e acabei não precisando escapar do apóstrofo ('). Você tem um exemplo em que falha?
@Dave Van den Eynde: Combinar os dois nomes de arquivos em uma linha, de acordo com o RFC6266, exceto o Android e o IE7 + 8, e atualizei o código para refletir isso. Obrigado pela sugestão.
@ Thilo: Não faço ideia do GoodReader ou de qualquer outro navegador que não seja. Você pode ter alguma sorte usando a abordagem do Android.
@Alex Zhukovskiy: Não sei por que, mas, como discutido no Connect , não parece funcionar muito bem.
fonte
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
e pular o navegador farejando? Isso funcionaria?Não há maneira interoperável para codificar nomes não ASCII
Content-Disposition
. A compatibilidade do navegador é uma bagunça .A sintaxe teoricamente correta para o uso de UTF-8 in
Content-Disposition
é muito estranha:filename*=UTF-8''foo%c3%a4
(sim, é um asterisco e sem aspas, exceto uma aspas vazia no meio)Esse cabeçalho é meio não muito padrão (a especificação HTTP / 1.1 reconhece sua existência , mas não exige que os clientes o suportem).
Existe uma alternativa simples e muito robusta: use uma URL que contenha o nome do arquivo que você deseja .
Quando o nome após a última barra é o desejado, você não precisa de cabeçalhos extras!
Esse truque funciona:
E se o seu servidor suportar a reescrita de URL (por exemplo,
mod_rewrite
no Apache), você poderá ocultar completamente a parte do script.Os caracteres nos URLs devem estar em UTF-8, codificados em url byte a byte:
fonte
/:id/:filename
método é realmente simples e funciona, obrigado!Content-Disposition
e criar nomes muito interessantes em vez (que será gerada a partir de seu caminho). Assim, a única solução para a guarda de uma sanidade é apenas a criaçãoContent-Disposition: attachment
e passando o nome do arquivo desejado como o último componente do caminho:O RFC 6266 descreve o " Uso do campo de cabeçalho de disposição de conteúdo no HTTP (Hypertext Transfer Protocol) ". Citando isso:
E na seção de exemplos :
No Apêndice D, há também uma longa lista de sugestões para aumentar a interoperabilidade. Ele também aponta para um site que compara implementações . Os testes de aprovação atuais adequados para nomes de arquivos comuns incluem:
filename
parâmetro " ".Esse RFC 5987, por sua vez, faz referência ao RFC 2231 , que descreve o formato real. 2231 é principalmente para correio, e 5987 nos diz quais partes também podem ser usadas para cabeçalhos HTTP. Não confunda isso com os cabeçalhos MIME usados dentro de um corpo
multipart/form-data
HTTP , que é governado pela RFC 2388 ( seção 4.4 em particular) e pelo rascunho do HTML 5 .fonte
O documento a seguir, vinculado ao rascunho da RFC mencionado por Jim em sua resposta, aborda mais a questão e definitivamente merece uma nota direta aqui:
Casos de teste para o cabeçalho HTTP-Disposition de conteúdo e codificação RFC 2231/2047
fonte
no asp.net mvc2 eu uso algo como isto:
Eu acho que se você não usar o mvc (2), poderia codificar o nome do arquivo usando
fonte
Coloque o nome do arquivo entre aspas duplas. Resolvido o problema para mim. Como isso:
http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
Eu testei várias opções. Os navegadores não suportam as especificações e agem de maneira diferente, acredito que aspas duplas é a melhor opção.
fonte
&
,%
,#
etc. Então ele resolve isso.Eu uso os seguintes trechos de código para codificação (assumindo que fileName contém o nome do arquivo e a extensão do arquivo, ou seja: test.txt):
PHP:
Java:
fonte
rawurlencode
no PHP pelo menos para ofilename*=
cabeçalho de disposição, já que évalue-chars
usado naext-value
RFC 6266-> RFC 5987 (consulte tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section -3.2.1 ) não permite espaço sem porcentagem de escape (filename=
por outro lado, parece que poderia permitir um espaço sem escape, embora apenas ASCII deva estar presente aqui). Não é necessário para codificar com o rigor cheio de rawurlencode, então alguns caracteres pode ser unescaped: gist.github.com/brettz9/8752120Na API da Web do ASP.NET, eu codifico o nome do arquivo:
fonte
Testei o seguinte código em todos os principais navegadores, incluindo Exploradores mais antigos (por meio do modo de compatibilidade), e funciona bem em qualquer lugar:
fonte
Acabei com o seguinte código no meu script "download.php" (baseado neste post do blog e nesses casos de teste ).
Isso usa a maneira padrão do nome do arquivo = "...", desde que haja apenas caracteres iso-latin1 e "safe" usados; caso contrário, ele adiciona o nome do arquivo * = UTF-8 '' de maneira codificada por url. De acordo com este caso de teste específico , ele deve funcionar a partir do MSIE9 e no recente FF, Chrome, Safari; na versão inferior do MSIE, deve oferecer um nome de arquivo que contenha a versão ISO8859-1 do nome do arquivo, com sublinhados nos caracteres que não estão nessa codificação.
Nota final: o max. O tamanho de cada campo de cabeçalho é 8190 bytes no apache. UTF-8 pode ter até quatro bytes por caractere; após rawurlencode, é x3 = 12 bytes por um caractere. Bastante ineficiente, mas ainda deve ser teoricamente possível ter mais de 600 "sorrisos"% F0% 9F% 98% 81 no nome do arquivo.
fonte
Se você estiver usando um back-end nodejs, poderá usar o seguinte código que encontrei aqui
fonte
encodeURI(str)
. Como exemplo com datas no nome do arquivo: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"No PHP, isso foi feito por mim (assumindo que o nome do arquivo seja codificado em UTF8):
Testado contra IE8-11, Firefox e Chrome.
Se o navegador puder interpretar o nome do arquivo * = utf-8, ele usará a versão UTF8 do nome do arquivo, caso contrário, o nome do arquivo decodificado. Se o seu nome de arquivo contiver caracteres que não podem ser representados na ISO-8859-1, você pode considerar o uso
iconv
.fonte
Apenas uma atualização desde que eu estava tentando todas essas coisas hoje em resposta a um problema do cliente
fonte
PHP framework Symfony 4 tem
$filenameFallback
emHeaderUtils::makeDisposition
. Você pode procurar nessa função para obter detalhes - ela é semelhante às respostas acima.Exemplo de uso:
fonte
Solução ASP clássica
A maioria dos navegadores modernos oferece suporte à aprovação de
Filename
comoUTF-8
agora, mas como foi o caso de uma solução de Upload de Arquivos que eu uso baseada no FreeASPUpload.Net (o site não existe mais, os links apontam para archive.org ) , não funcionaria como a análise do O binário confiava na leitura de cadeias codificadas em ASCII de byte único, o que funcionava bem quando você passava dados codificados em UTF-8 até chegar aos caracteres que ASCII não suporta.No entanto, consegui encontrar uma solução para obter o código para ler e analisar o binário como UTF-8.
O crédito é transferido para o Pure ASP File Upload implementando a
BytesToString()
funçãoinclude_aspuploader.asp
no meu próprio códigoUTF-8
.Links Úteis
Dados de várias partes / formulário e UTF-8 em um aplicativo ASP Classic
Diferenças de formato Unicode, UTF, ASCII, ANSI
fonte
Tivemos um problema semelhante em um aplicativo Web e terminamos lendo o nome do arquivo no HTML
<input type="file">
e definindo-o no formulário codificado por URL em um novo HTML<input type="hidden">
. É claro que tivemos que remover o caminho como "C: \ fakepath \" retornado por alguns navegadores.Obviamente, isso não responde diretamente à pergunta dos OPs, mas pode ser uma solução para outros.
fonte
Normalmente codifico por URL (com% xx) os nomes dos arquivos e parece funcionar em todos os navegadores. Você pode querer fazer alguns testes de qualquer maneira.
fonte