Вопрос

Я реализовал простой механизм загрузки файлов.Когда пользователь нажимает на имя файла, файл загружается с этими 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

Я также поддерживаю японские имена файлов.Чтобы сделать это, я кодирую имя файла с помощью этого 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");
}

До сих пор это работало хорошо, пока кто-то не обнаружил, что это плохо работает с длинными именами файлов.Например: あああああああああああああああ2008.10.1あ.doc.Если я изменю одну из однобайтовых точек на однобайтовое подчеркивание или удалю первый символ, все будет работать нормально.т.е. это зависит от длины и URL-кодировки символа точки.Ниже приведено несколько примеров.

Это сломано (あああああああああああああああ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;

Все в порядке (あああああああああああああああ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;

Это тоже прекрасно (あああああああああああああああ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;

У кого-нибудь есть догадки?

Это было полезно?

Решение

gmail обрабатывает экранирование имени файла несколько по-другому:имя файла заключено в кавычки (двойные кавычки), а однобайтовые точки не экранируются URL.Таким образом, длинное имя файла в вопросе в порядке.

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"

Однако по-прежнему существует ограничение (по-видимому, только для IE) на длину имени файла в байтах (я полагаю, ошибка).Таким образом, даже если имя файла состоит только из однобайтовых символов, начало имени файла усекается.Ограничение составляет около 160 байт.

Другие советы

Как упоминалось выше, невозможно заставить работать Content-Disposition и Unicode во всех основных браузерах без того, чтобы браузер не отслеживал и не возвращал разные заголовки для каждого из них.

Мое решение состояло в том, чтобы полностью избежать заголовка Content-Disposition и добавить имя файла в конец URL-адреса, чтобы заставить браузер думать, что он получает файл напрямую.например ,

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

Это, естественно, предполагает, что вы знаете имя файла при создании ссылки, хотя заголовок быстрого перенаправления может задать его по запросу.

Основная проблема здесь заключается в том, что IE не поддерживает соответствующий RFC, здесь:RFC2231.Видишь указатели и тестовые примеры.Кроме того, обходной путь, который вы используете для IE (просто используя UTF-8 с экранированием процентов), имеет несколько дополнительных проблем;это может работать не во всех локализациях (насколько я помню, метод не работает в Корее, если IE не настроен на постоянное использование UTF-8 в URL-адресах, которые не используются по умолчанию), и, как упоминалось ранее, существуют ограничения по длине (я слышал, что это исправлено в IE8, но я еще не пробовал).

Я думаю, что эта проблема исправлена в IE8, я видел, как она работает в IE 8.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top