Pregunta

He implementado un mecanismo simple de carga y descarga de archivos. Cuando un usuario hace clic en un nombre de archivo, el archivo se descarga con estos encabezados HTTP:

HTTP/1.1 200 OK
Date: Tue, 30 Sep 2008 14:00:39 GMT
Server: Microsoft-IIS/6.0
Content-Disposition: attachment; filename=filename.doc;
Content-Type: application/octet-stream
Content-Length: 10754

También apoyo nombres de archivos japoneses. Para hacer eso, codifico el nombre del archivo con este método java:

private String encodeFileName(String name) throws Exception{
    String agent = request.getHeader("USER-AGENT");
    if(agent != null && agent.indexOf("MSIE") != -1){ // is IE
        StringBuffer res = new StringBuffer();
        char[] chArr = name.toCharArray();
        for(int j = 0; j < chArr.length; j++){
            if(chArr[j] < 128){ // plain ASCII char
                if (chArr[j] == '.' && j != name.lastIndexOf("."))
                    res.append("%2E");
                else
                    res.append(chArr[j]);
            }
            else{ // non-ASCII char
                byte[] byteArr = name.substring(j, j + 1).getBytes("UTF8");
                for(int i = 0; i < byteArr.length; i++){
                    // byte must be converted to unsigned int
                    res.append("%").append(Integer.toHexString((byteArr[i]) & 0xFF));
                }
            }
        }
        return res.toString();
    }
    // Firefox/Mozilla
    return MimeUtility.encodeText(name, "UTF8", "B");
}

Funcionó bien hasta ahora, hasta que alguien descubrió que no funciona bien con nombres de archivo largos. Por ejemplo: ? ? ? ? ? 2008.10.1 ? .doc . Si cambio uno de los puntos de un solo byte a un subrayado de un solo byte, o si quito el primer carácter, funciona bien. es decir, depende de la longitud y la codificación URL de un carácter de punto. Los siguientes son algunos ejemplos.

Esto está roto ( ? ? ? ? ? 2008.10.1 ? .doc ):

Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008%2E10%2E1%e3%81%82.doc;

Esto está bien ( code ? ? ? _ 2008_10.1 ? .doc ):

Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008_10%2E1%e3%81%82.doc;

Esto también está bien ( ? ? ? ? ? 2008.10.1 ? .doc ):

Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008%2E10%2E1%e3%81%82.doc;

¿Alguien tiene una pista?

¿Fue útil?

Solución

gmail maneja el nombre del archivo que se escapa de manera diferente: el nombre del archivo se cita (comillas dobles), y los períodos de un byte no se escapan de la URL. De esta manera, el nombre de archivo largo en la pregunta está bien.

Content-Disposition: attachment; filename="%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%822008.10.1%E3%81%82.doc"

Sin embargo, todavía hay una limitación (aparentemente solo para IE) en la longitud del byte del nombre del archivo (un error, supongo). Por lo tanto, incluso si el nombre del archivo está compuesto únicamente de caracteres de un solo byte, el principio del nombre del archivo se trunca. La limitación es de alrededor de 160 bytes.

Otros consejos

Como se mencionó anteriormente, es imposible que Content-Disposition y Unicode funcionen en todos los navegadores principales sin que el navegador detecte y devuelva encabezados diferentes para cada uno.

Mi solución fue evitar el encabezado Content-Disposition por completo, y agregar el nombre del archivo al final de la URL para engañar al navegador y hacer que crea un archivo directamente. por ejemplo

http://www.xyz.com/cgi-bin/dynamic.php/あああああああああああああああ2008.10.1あ.doc

Esto, naturalmente, supone que conoces el nombre del archivo cuando crees el enlace, aunque un encabezado de redirección rápida podría establecerlo a pedido.

El problema principal aquí es que IE no es compatible con el RFC relevante, aquí: RFC2231. Consulte punteros y casos de prueba . Además, la solución que utiliza para IE (solo con el porcentaje de escape UTF-8) tiene varios problemas adicionales; puede que no funcione en todas las configuraciones regionales (que yo recuerde, el método falla en Corea a menos que IE esté configurado para usar siempre UTF-8 en las URL, que no es el predeterminado) y, como se mencionó anteriormente, hay límites de longitud (I escuche que eso está arreglado en IE8, pero aún no lo he intentado).

Creo que este problema se solucionó en IE8, lo he visto funcionar en IE 8.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top