我有一个servlet需要写出具有用户可配置名称的文件。我正在尝试使用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
实例化新的File对象后,%2F
序列会自动转换为正斜杠,最终路径不正确。有人知道解决这个问题的正确方法吗?
问题的核心似乎是那个
uri.equals( new File(uri).toURI() ) == FALSE
当URI中有%2F
时。
我打算逐字使用URLEncoded字符串,而不是尝试使用File(uri)
构造函数。
答案 0 :(得分:5)
new File(URI)
根据URI#getPath()
获取的路径构建文件,而不是 - 您期望的那样 - URI#getRawPath()
。这看起来像是“按设计”的特征。
您有两个选择:
fn
上运行URLEncoder#encode()
两次(注意:encode()
,而不是encoder()
)。new File(String)
。答案 1 :(得分:2)
我认为@BalusC已经解决了代码中的直接问题。我只想指出其他一些问题
dir.toURI().toASCIIString()
和URLEncoder.encoder(fn, "UTF-8").toString()
表达式确实做了不同的事情。
第一个,将URI编码为字符串,根据URI语法应用URI编码规则。因此,例如,路径组件中的“/”将不会被编码,但查询或片段组件中的“/”将被编码为%2F。
第二个,使用编码规则对fn
字符串进行编码,而不参考字符串的内容。
File(URI)
构造函数从文件URI到文件的映射是system dependent and undocumented。我有点惊讶它解码%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());