【问题标题】:Why does Java automatically decode %2F in URI encoded filenames?为什么 Java 会自动解码 URI 编码文件名中的 %2F?
【发布时间】:2010-05-04 13:41:46
【问题描述】:

我有一个 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) 构造函数。

【问题讨论】:

  • 这样做当然是正确的。如果您在文件名中需要逐字逐句 %2F,则在 URI 中使用时必须正确转义:%252F
  • 我想你误会了。我不想对“%2F”进行编码,我想对“/”进行编码,以便创建一个合法的文件名,该文件名代表包含正斜杠的用户指定名称。
  • 出于兴趣:我知道这些是文件 URI,但如果它们是 http URI,网络服务器不应该处理 %F2/ 相同吗?另外:由于/ 在 Windows 文件名中无效,因此这样的文件 URI 似乎没有意义,或者?
  • @RoToRa:直截了当,他只是想要在文件名中使用 URL 编码字符的能力。这不能正常工作,因为new File(URI) 会解码它们。

标签: java file encoding uri


【解决方案1】:

new File(URI) 根据URI#getPath() 获得的路径而不是-您所期望的-URI#getRawPath() 构建文件。这看起来像是“设计”的功能。

你有两个选择:

  1. fn 上运行URLEncoder#encode() 两次(注意:encode(),而不是encoder())。
  2. 请改用new File(String)

【讨论】:

  • 有道理。它记录在任何地方,还是 File 类保证“new File(f.toURI()).equals(f.getAbsoluteFile())”暗示它?
  • @Lucas - 没有记录;看我的回答
【解决方案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 解释了原因。结论是,使用显式依赖于系统的机制(“file:”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());

【讨论】:

    猜你喜欢
    • 2020-02-10
    • 2015-05-19
    • 2012-04-23
    • 2019-10-04
    • 1970-01-01
    • 2021-06-19
    • 2017-06-26
    • 2012-05-01
    • 2013-03-26
    相关资源
    最近更新 更多