Повреждение имени файла при загрузке файла (IE) - PullRequest
3 голосов
/ 30 сентября 2008

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

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

Ответы [ 4 ]

6 голосов
/ 30 сентября 2008

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 байтов.

2 голосов
/ 21 декабря 2009

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

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

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

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

1 голос
/ 01 мая 2009

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

0 голосов
/ 16 августа 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...