2011-01-19 18 views
6

¿Cómo puedo establecer nombres de archivos localizados en java? En la actualidad cada vez que hago clic en un archivo localizado que tiene un nombre de archivo no ASCII en mi aplicación, el cuadro de diálogo de guardar aparece, pero no muestra el nombre de archivo juego de caracteres está por encima de ISO-88859-1.Nombres de archivos localizados en Java

Este es mi código que guarda el archivo.

  InputStream inputStream = null; 
try { 
    response.resetBuffer(); 
    response.setContentType(fileStream.getContentType()); 
    response.setContentLength((int) fileStream.getContentLength()); 
    response.addHeader("Content-Disposition", 
    "attachment;filename=\"" + fileName + "\""); 
    ServletOutputStream stream = response.getOutputStream(); 
    byte[] buffer = new byte[1024]; 
    int read = 0; 
    int total = 0; 
    inputStream = fileStream.getInputStream(); 
    while ((read = inputStream.read(buffer)) > 0) { 
    stream.write(buffer, 0, read); 
    total += read; 
    } 
    response.flushBuffer(); 
} finally { 
    if (inputStream != null) { 
    inputStream.close(); 
    } 
} 

Sería muy útil si alguien pudiera compartir sus ideas sobre cómo resolver este problema. Gracias de antemano.

Respuesta

13

Lo que gustafc dice es correcto, pero no te lleva a donde quieres estar. RFC 2231 le permite utilizar un formato alternativo para los parámetros que no son ASCII Content-Type y Content-Disposition, pero no todos los navegadores lo admiten. La forma en que es más probable que funcione, por desgracia, es ignorar lo que dice el RFC 2183 y utilizar RFC 2047 encoded-words en la respuesta:

response.addHeader("Content-Disposition", "attachment; " + 
    "filename=\"" + MimeUtility.encodeWord(fileName, "utf-8", "Q") + "\""); 

Tenga en cuenta que esto puede no funcionar para todos los navegadores. Algunas variantes de IE requieren que la URL a codificar el valor en lugar:

response.addHeader("Content-Disposition", 
    "attachment; filename=" + URLEncoder.encode(filename, "utf-8")); 
+0

DKarp, Este código fue realmente útil. Ahora podría obtener los resultados deseados en todos los navegadores que no sean IE. Con IE al descargar el archivo, está codificando el nombre del archivo para que se muestre en el formato correcto, pero agrega la URL completa y cuando intento descargar un archivo .xls, muestra un cuadro de progreso de descarga con una alerta que dice "Internet Explorer no pudo abrir este sitio. El sitio no está disponible o no se puede encontrar ". Una vez más quisiera que me señalaras en la dirección correcta. Muchas gracias por tu ayuda. – Hitatichi

+0

¿Cuál es el código que está utilizando para configurar el encabezado 'Content-Disposition' para IE? Creo que algunas versiones de IE pueden no funcionar bien con el plegado de encabezado, así que asegúrate de no poner una nueva línea extra en el encabezado ... – dkarp

+0

Utilicé URLEncoder para IE exactamente como lo especificaste en la respuesta. response.addHeader ("Content-Disposition", "attachment; filename =" + URLEncoder.encode (filename, "utf-8")); – Hitatichi

2

De section 2.3 in the spec, parece que no puede utilizar caracteres no US-ASCII:

actual [RFC 2045] gramática restringe los valores de parámetros (y por tanto nombres de archivo Content-Disposition) a US-ASCII. Reconocemos la gran conveniencia de de permitir conjuntos de caracteres arbitrarios en nombres de archivo, pero está más allá del alcance de este documento definir los mecanismos necesarios . Esperamos que la especificación básica [RFC 1521] `valor ' se modifique algún día para permitir el uso de caracteres que no sean US-ASCII , en cuyo momento se debe usar el mismo mecanismo en el parámetro Content-Disposition filename.

+0

Esto es exacto, pero inútil. :) – dkarp

+0

Gustafc, gracias por su tiempo y los RFC que especificaron el motivo de estos resultados no deseados. – Hitatichi

4

me enfrentaba a problemas similares con los nombres de archivo que contienen griego characters.I utiliza el código proporcionado en la respuesta anterior (gracias a mis dkarp) combinado con detectar qué navegador es usado este es el resultado:

 
String user_agent = request.getHeader("user-agent"); 
boolean isInternetExplorer = (user_agent.indexOf("MSIE") > -1); 
if (isInternetExplorer) { 
    response.setHeader("Content-disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "utf-8") + "\""); 
} else { 
    response.setHeader("Content-disposition", "attachment; filename=\"" + MimeUtility.encodeWord(filename) + "\""); 
} 

he comprobado con Firefox 3.6, Chrome 10.0 e Internet Explorer 8 y parece que funciona bien.

1

Aunque es una vieja pregunta, sigue siendo real. Encontré una solución que funciona para todos mis navegadores.

Ver mi puesto en otro hilo:
Java servlet download filename special characters

En resumen, los navegadores esperan que el valor de filename parámetro se codifica en los navegadores codificación nativa (si no se especifica un conjunto de caracteres diferente para filename parámetro). La codificación nativa del navegador suele ser utf-8 (FF, Opera, Chrome), pero para IE es win-1250. Por lo tanto, si ponemos valor en filename parametr, que está codificado por utf-8/win-1250 según el navegador del usuario, debería funcionar.

Por ejemplo, si tenemos fichero llamado omáčka.xml,
para Firefox, Opera y Chrome i respuesta esta cabecera (codificado en UTF-8):

Content-Disposition: attachment; filename="omáčka.xml" 

y para IE i respuesta esta cabecera (codificada en la victoria-1250):

Content-Disposition: attachment; filename="omáèka.jpg" 

ejemplo Java es in my post que se menciona anteriormente.

Nota # 1 (@dkarp):

estar al tanto de uso de URLEncoder.encode() ya que este método no codifica cadena de entrada en codificación URL. Este método codifica las cadenas de entrada en la codificación de formularios, que es muy similar, pero difiere en algunos casos, por ejemplo, el carácter espacial '' está codificado como '+' en lugar de '% 20'.

Para realizar correctamente la codificación URL que debe usar en lugar de clase URI:

URI uri = new URI(null, null, "foo-ä-€.html", null); 
System.out.println(uri.toASCIIString()); 
Cuestiones relacionadas