То, почему Java автоматически декодирует %2F в URI, закодировало имена файлов?

У меня есть сервлет, который должен выписать файлы, которые имеют настраиваемое пользователем имя. Я пытаюсь использовать кодирование URI для надлежащего выхода из специальных символов, но JRE, кажется, автоматически преобразовывает закодированные наклонные черты вправо %2F в разделители пути.

Пример:

File   dir = new File("C:\Documents and Setting\username\temp");
String fn  = "Top 1/2.pdf";
URI    uri = new URI( dir.toURI().toASCIIString() + URLEncoder.encoder( fn, "ASCII" ).toString() );
File   out = new File( uri );

System.out.println( dir.toURI().toASCIIString() );
System.out.println( URLEncoder.encode( fn, "ASCII" ).toString() );
System.out.println( uri.toASCIIString() );
System.out.println( output.toURI().toASCIIString() );

Вывод:

file:/C:/Documents%20and%20Settings/username/temp/
Top+1%2F2.pdf   
file:/C:/Documents%20and%20Settings/username/temp/Top+1%2F2.pdf
file:/C:/Documents%20and%20Settings/username/temp/Top+1/2.pdf

После того, как новый объект Файла инстанцируют, %2F последовательность автоматически преобразовывается в наклонную черту вправо, и я заканчиваю с неправильным путем. Кто-либо знает надлежащий способ приблизиться к этой проблеме?

Ядро проблемы, кажется, это

uri.equals( new File(uri).toURI() ) == FALSE

когда существует a %2F в URI.

Я планирую просто использовать строку URLEncoded дословно вместо того, чтобы пытаться использовать File(uri) конструктор.

6
задан Makoto 9 September 2015 в 15:48
поделиться

2 ответа

новый файл (URI) создает файл на основе пути, полученного с помощью URI # getPath () вместо-чего вы ожидали- URI # getRawPath () . Это похоже на особенность «по замыслу».

У вас есть 2 варианта:

  1. Выполнить URLEncoder # encode () на fn дважды (примечание: encode () , а не кодировщик () ).
  2. Вместо этого используйте новый файл (строка) .
5
ответ дан 17 December 2019 в 00:05
поделиться

Я думаю, что @BalusC решил прямую проблему в вашем коде. Я просто хотел бы указать на другую проблему

dir.toURI (). ToASCIIString () и URLEncoder.encoder (fn, "UTF-8"). ToString () Выражения на самом деле делают разные вещи.

  • Первый кодирует URI как строку, применяя правила кодирования URI в соответствии с грамматикой URI. Так, например, '/' в компоненте пути не будет кодироваться, а '/' в компонентах запроса или фрагмента будет закодирован как% 2F.

  • Второй кодирует строку fn , применяя правила кодирования без ссылки на содержимое строки.

Отображение конструктора файла (URI) из URI файла в файл зависит от системы и недокументировано . Я немного удивлен, что он декодирует % 2F , но делает то, что делает, и @BalusC объясняет почему. Вывод заключается в том, что потенциально проблематично использовать механизм (URI "файл:"), который явно зависит от системы.

Наконец, неправильно комбинировать такие строки компонентов URI. Это должно быть либо

URI uri = new URI(
        dir.toURI().toString() +
        URLEncoder.encoder(fn, "UTF-8").toString();

, либо

URI uri = new URI(
        dir.toURI().toASCIIString() +
        URLEncoder.encoder(fn, "ASCII").toString());
2
ответ дан 17 December 2019 в 00:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: