Las aplicaciones web que desean forzar la descarga de un recurso en lugar de representarlo directamente en un navegador web emiten un Content-Disposition
encabezado en la respuesta HTTP del formulario:
Content-Disposition: attachment; filename=FILENAME
El filename
parámetro puede usarse para sugerir un nombre para el archivo en el que el navegador descarga el recurso. RFC 2183 (Content-Disposition), sin embargo, establece en la sección 2.3 (El parámetro de nombre de archivo) que el nombre de archivo solo puede usar caracteres US-ASCII:
La gramática actual [RFC 2045] restringe los valores de los parámetros (y, por lo tanto, los nombres de los archivos de disposición de contenido) a US-ASCII. Reconocemos la gran conveniencia de permitir conjuntos de caracteres arbitrarios en los nombres de archivo, pero está fuera del alcance de este documento definir los mecanismos necesarios.
Sin embargo, existe evidencia empírica de que los navegadores web más populares de hoy en día parecen permitir caracteres que no son ASCII de EE. UU. Pero (por falta de un estándar) no están de acuerdo con el esquema de codificación y la especificación del juego de caracteres del nombre del archivo. La pregunta es, entonces, ¿cuáles son los diversos esquemas y codificaciones empleados por los navegadores populares si el nombre de archivo "naïvefile" (sin comillas y donde la tercera letra es U + 00EF) necesita codificarse en el encabezado Content-Disposition?
A los efectos de esta pregunta, los navegadores populares son:
- Firefox
- explorador de Internet
- Safari
- Google Chrome
- Ópera
fuente
Content-Disposition: attachment
.Respuestas:
Se discute esto, incluidos los enlaces a las pruebas del navegador y la compatibilidad con versiones anteriores, en el RFC 5987 propuesto , "Conjunto de caracteres y codificación de idioma para parámetros de campo de encabezado del protocolo de transferencia de hipertexto (HTTP)".
RFC 2183 indica que dichos encabezados deben codificarse de acuerdo con RFC 2184 , que estaba obsoleto por RFC 2231 , cubierto por el borrador de RFC anterior.
fuente
Content-Disposition: filename="foo, bar.pdf"
. El resultado es que firefox descarga el archivo correctamente pero mantiene la.part
extensión (pfoo,bar.pdf-1.part
. Ej .). Entonces, por supuesto, el archivo no se abrirá correctamente porque la aplicación no está asociada.part
. Otros caracteres ASCII parecen funcionar bien.Sé que esta es una publicación antigua pero sigue siendo muy relevante. He descubierto que los navegadores modernos son compatibles con rfc5987, que permite la codificación utf-8, codificada en porcentaje (codificada en url). Entonces Naïve file.txt se convierte en:
Safari (5) no es compatible con esto. En su lugar, debe usar el estándar Safari para escribir el nombre del archivo directamente en su encabezado codificado utf-8:
IE8 y versiones anteriores tampoco lo admiten y debe usar el estándar IE de codificación utf-8, codificado porcentual:
En ASP.Net utilizo el siguiente código:
Probé lo anterior usando IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Actualización de noviembre de 2013:
Aquí está el código que uso actualmente. Todavía tengo que soportar IE8, así que no puedo deshacerme de la primera parte. Resulta que los navegadores en Android usan el administrador de descargas de Android incorporado y no pueden analizar de manera confiable los nombres de archivos de la manera estándar.
Lo anterior ahora probado en IE7-11, Chrome 32, Opera 12, FF25, Safari 6, usando este nombre de archivo para descargar: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§! # ¤% & () = `@ £ $ € {[]} + ´¨ ^ ~ '-_,;. txt
En IE7 funciona para algunos caracteres pero no para todos. ¿Pero a quién le importa IE7 hoy en día?
Esta es la función que uso para generar nombres de archivos seguros para Android. Tenga en cuenta que no sé qué caracteres son compatibles con Android, pero he probado que estos funcionan con seguridad:
@TomZ: Probé en IE7 e IE8 y resultó que no necesitaba escapar del apóstrofe ('). ¿Tienes un ejemplo donde falla?
@Dave Van den Eynde: la combinación de los dos nombres de archivo en una línea de acuerdo con RFC6266 funciona a excepción de Android e IE7 + 8 y he actualizado el código para reflejar esto. Gracias por la sugerencia.
@Thilo: No tengo idea sobre GoodReader o cualquier otro no navegador. Es posible que tenga suerte con el enfoque de Android.
@ Alex Zhukovskiy: No sé por qué, pero como se discutió en Connect , no parece funcionar muy bien.
fuente
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
y omitir el navegador olfateando? Funcionaría eso?No hay una forma interoperable de codificar nombres que no sean ASCII
Content-Disposition
. La compatibilidad del navegador es un desastre .La sintaxis teóricamente correcta para el uso de UTF-8 en
Content-Disposition
es muy extraña:filename*=UTF-8''foo%c3%a4
(sí, es un asterisco y no hay comillas, excepto una comilla simple vacía en el medio)Este encabezado es un poco no bastante estándar (la especificación HTTP / 1.1 reconoce su existencia , pero no requiere que los clientes lo admitan).
Hay una alternativa simple y muy robusta: use una URL que contenga el nombre de archivo que desee .
Cuando el nombre después de la última barra es el que desea, ¡no necesita encabezados adicionales!
Este truco funciona:
Y si su servidor admite la reescritura de URL (por ejemplo,
mod_rewrite
en Apache), puede ocultar completamente la parte del script.Los caracteres en las URL deben estar en UTF-8, codificados por bytes:
fuente
/:id/:filename
método es realmente simple y funciona, ¡gracias!Content-Disposition
y crear nombres de archivo muy interesantes en su lugar (que se generan a partir de su trayectoria). Entonces, la única solución para mantener la cordura es simplemente configurarContent-Disposition: attachment
y pasar el nombre de archivo deseado como el último componente de la ruta:RFC 6266 describe el " Uso del campo de encabezado de disposición de contenido en el Protocolo de transferencia de hipertexto (HTTP) ". Citando de eso:
Y en su sección de ejemplos :
En el Apéndice D también hay una larga lista de sugerencias para aumentar la interoperabilidad. También apunta a un sitio que compara implementaciones . Las pruebas actuales aprobadas para todos los nombres de archivos comunes incluyen:
filename
parámetro " ".Ese RFC 5987 a su vez hace referencia al RFC 2231 , que describe el formato real. 2231 es principalmente para correo, y 5987 nos dice qué partes pueden usarse también para encabezados HTTP. No confunda esto con los encabezados MIME utilizados dentro de un cuerpo
multipart/form-data
HTTP , que se rige por RFC 2388 ( sección 4.4 en particular) y el borrador HTML 5 .fuente
El siguiente documento vinculado desde el borrador de RFC mencionado por Jim en su respuesta aborda la pregunta y definitivamente vale la pena una nota directa aquí:
Casos de prueba para encabezado de disposición de contenido HTTP y codificación RFC 2231/2047
fuente
en asp.net mvc2 uso algo como esto:
Supongo que si no usas mvc (2) podrías codificar el nombre de archivo usando
fuente
Ponga el nombre del archivo entre comillas dobles. Resolvió el problema para mí. Me gusta esto:
http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
He probado múltiples opciones. Los navegadores no admiten las especificaciones y actúan de manera diferente, creo que las comillas dobles son la mejor opción.
fuente
&
,%
,#
etc Por lo tanto soluciona.Utilizo los siguientes fragmentos de código para codificar (suponiendo que fileName contiene el nombre de archivo y la extensión del archivo, es decir: test.txt):
PHP:
Java:
fuente
rawurlencode
en PHP al menos para elfilename*=
encabezado de disposición, ya que sevalue-chars
utiliza enext-value
RFC 6266-> RFC 5987 (consulte tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section -3.2.1 ) no permite espacio sin un porcentaje de escape (filename=
, por otro lado, parece que podría permitir un espacio sin escapar en absoluto, aunque solo ASCII debería estar presente aquí). No es necesario codificar con toda la rigurosidad del código rawurlen, por lo que algunos caracteres pueden quedar libresEn ASP.NET Web API, codifico el nombre del archivo url:
fuente
Probé el siguiente código en todos los principales navegadores, incluidos los exploradores más antiguos (a través del modo de compatibilidad), y funciona bien en todas partes:
fuente
Terminé con el siguiente código en mi script "download.php" (basado en esta publicación de blog y estos casos de prueba ).
Utiliza la forma estándar de filename = "..." siempre que solo se usen caracteres iso-latin1 y "seguros"; si no, agrega el nombre de archivo * = UTF-8 '' codificado en url. De acuerdo con este caso de prueba específico , debería funcionar desde MSIE9 en adelante, y en FF reciente, Chrome, Safari; en la versión inferior de MSIE, debe ofrecer un nombre de archivo que contenga la versión ISO8859-1 del nombre de archivo, con guiones bajos en caracteres que no están en esta codificación.
Nota final: el max. El tamaño de cada campo de encabezado es de 8190 bytes en Apache. UTF-8 puede tener hasta cuatro bytes por carácter; después de rawurlencode, es x3 = 12 bytes por un caracter. Bastante ineficiente, pero debería ser teóricamente posible tener más de 600 "sonrisas"% F0% 9F% 98% 81 en el nombre del archivo.
fuente
Si está utilizando un backend de nodejs, puede usar el siguiente código que encontré aquí
fuente
encodeURI(str)
. Como ejemplo con fechas en el nombre del archivo: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"En PHP esto lo hizo por mí (suponiendo que el nombre del archivo esté codificado en UTF8):
Probado contra IE8-11, Firefox y Chrome.
Si el navegador puede interpretar el nombre de archivo * = utf-8 , usará la versión UTF8 del nombre de archivo; de lo contrario, usará el nombre de archivo descodificado. Si su nombre de archivo contiene caracteres que no se pueden representar en ISO-8859-1, puede considerar usarlos
iconv
.fuente
Solo una actualización ya que estaba probando todo esto hoy en respuesta a un problema del cliente
fuente
PHP framework Symfony 4 tiene
$filenameFallback
enHeaderUtils::makeDisposition
. Puede buscar detalles en esta función; es similar a las respuestas anteriores.Ejemplo de uso:
fuente
Solución ASP clásica
La mayoría de los navegadores modernos admiten pasar el
Filename
comoUTF-8
ahora, pero como fue el caso con una solución de carga de archivos que uso que se basa en FreeASPUpload.Net (el sitio ya no existe, los puntos de enlace a archive.org ) no funcionaría como el análisis del binario se basó en la lectura de cadenas codificadas ASCII de un solo byte, que funcionó bien cuando pasó los datos codificados UTF-8 hasta llegar a los caracteres que ASCII no admite.Sin embargo, pude encontrar una solución para obtener el código para leer y analizar el binario como UTF-8.
El crédito se destina a Pure ASP File Upload mediante la implementación de la
BytesToString()
función desdeinclude_aspuploader.asp
mi propio código, pude hacer que losUTF-8
nombres de archivo funcionen.Enlaces útiles
Multipart / form-data y UTF-8 en una aplicación ASP Classic
Diferencias de formato Unicode, UTF, ASCII, ANSI
fuente
Tuvimos un problema similar en una aplicación web y terminamos leyendo el nombre de archivo del HTML
<input type="file">
y configurándolo en el formulario codificado en URL en un nuevo HTML<input type="hidden">
. Por supuesto, tuvimos que eliminar la ruta como "C: \ fakepath \" que algunos navegadores devuelven.Por supuesto, esto no responde directamente a la pregunta de los OP, pero puede ser una solución para otros.
fuente
Normalmente codifico URL (con% xx) los nombres de archivo, y parece funcionar en todos los navegadores. Es posible que desee hacer algunas pruebas de todos modos.
fuente