Pergunta

Eu tenho implementado um mecanismo de upload-de download de arquivo simples. Quando um usuário clica em um nome de arquivo, o arquivo é baixado com estes cabeçalhos 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

Eu também suportar nomes de arquivos japoneses. A fim de fazer isso, eu codificar o nome do arquivo com 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");
}

Isso funcionou bem até agora, até que alguém descobriu que ele não funciona bem com nomes de arquivo longos. Por exemplo: あああああああああああああああ2008.10.1あ.doc. Se eu mudar um dos pontos de byte único para um sublinhado de byte único, ou se eu remover o primeiro caractere, ele funciona OK. ou seja, depende do comprimento e URL-codificação de um caractere de ponto. Seguem-se alguns exemplos.

Esta é quebrado (あああああああああああああああ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;

Este é OK (あああああああああああああああ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;

Esta é também fino (あああああああああああああああ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;

Alguém tem uma pista?

Foi útil?

Solução

alças gmail nome do arquivo escapar um pouco diferente: o nome do arquivo é citado (aspas), e períodos de byte único não são escapou-URL. Desta forma, o nome de arquivo longo na questão é OK.

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"

No entanto, ainda há uma limitação (aparentemente IE-only) no byte de comprimento do nome do arquivo (um bug, presumo). Assim, mesmo se o nome do arquivo é feito de apenas caracteres de byte único, o início do nome do arquivo é truncado. A limitação é de cerca de 160 bytes.

Outras dicas

Como mencionado acima, Content-Disposition e Unicode é impossível começar a trabalhar todos os principais navegadores sem navegador cheirar e retornando cabeçalhos diferentes para cada um.

A minha solução foi evitar o cabeçalho Content-Disposition inteiramente, e anexar o nome do arquivo para o final da URL para enganar o navegador em pensar que estava ficando um arquivo diretamente. por exemplo.

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

Isto, naturalmente, pressupõe que você saiba o nome do arquivo quando você cria o link, embora um cabeçalho de redirecionamento rápido poderia defini-lo sob demanda.

O principal problema aqui é que o IE não suporta a RFC relevantes, aqui: RFC2231. Veja ponteiros e casos de teste . Além disso, a solução que você usa para o IE (apenas usando por cento escapou UTF-8) tem vários problemas adicionais; Ele pode não funcionar em todos os locais (tanto quanto eu recordar, o método falha na Coreia, a menos que o IE é configurado para usar sempre UTF-8 em URLs que não é o padrão), e, como mencionado anteriormente, existem limites de comprimento (I ouvir que que foi corrigido no IE8, mas eu não tentei ainda).

Eu acho que este problema é corrigido no IE8, eu já vi isso funcionar no IE 8.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top