【问题标题】:servlet file upload filename encodingservlet 文件上传文件名编码
【发布时间】:2011-06-28 14:56:52
【问题描述】:

我正在使用 Apache Commons Fileupload 工具进行标准文件上传。我的问题是,如果上传文件包含特殊字符(á、é、ú 等),我无法获得正确的文件名。它们都被转换为?迹象。

request.getCharacterEncoding() 表示 UTF-8,但我在字符串 fileItem.getName() 中得到的字节对于我的所有特殊字符都是相同的。

你能帮我看看有什么问题吗?

(一些细节:在 Windows 上使用 Firefox 3.6.12、Weblogic 10.3)

这是我的代码 sn-p:

 public CommandMsg(HttpServletRequest request) {
    Enumeration names = null;
    if (isMultipart(request)) {
      FileItemFactory factory = new DiskFileItemFactory();
      ServletFileUpload upload = new ServletFileUpload(factory);
      try {
        List uploadedItems = upload.parseRequest(request);
        Iterator i = uploadedItems.iterator();
        FileItem fileItem = null;
        while (i.hasNext()) {
          fileItem = (FileItem) i.next();
          if (fileItem.isFormField()) {
            // System.out.println("isFormField");
            setAttribute(fileItem.getFieldName(), fileItem.getString());
          } else {
            String enc = "utf-8";
            enc = request.getCharacterEncoding();
            String fileName = fileItem.getName();
            byte[] fnb = fileItem.getName().getBytes();
            byte[] fnb2 = null;
            try {
                fnb2 = fileItem.getName().getBytes(enc);
                String t1 = new String(fnb);
                String t2 = new String(fnb2);
                String t3 = new String(fnb, enc);
                String t4 = new String(fnb2, enc);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            setAttribute(fileItem.getFieldName(), fileItem);
          }
        }
      } catch (FileUploadException ex) {
        ex.printStackTrace();
      }

// etc..

【问题讨论】:

  • 您是否尝试过使用和不解码文件名来获取文件名?在一个广泛使用的库中出现这样的问题,有点奇怪。
  • 是的,如您所见,第一次尝试是:“String fileName = fileItem.getName();”这很糟糕。所有其他行(t1..4)只是绝望的尝试.. :-)

标签: java servlets file-upload character-encoding apache-commons


【解决方案1】:

我遇到了同样的问题,就这样解决了。

ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8"); 

FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
    FileItemStream item = iter.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if (item.isFormField()) {
        String value = Streams.asString(stream, "UTF-8");
    } 
}

如果您的代码基于http://commons.apache.org/fileupload/streaming.html 中提供的示例,那么您需要确保在上面的两个位置设置了 UTF-8。

【讨论】:

  • 克里斯托夫 你成就了我的一天。很遗憾不得不编写这样的样板代码,但它运行良好:我花了半天时间查看 html 部分,而“问题”在服务器端......;)
  • 您不需要显式处理流,只需使用FileItem#getString(String),您可以在其中指定编码,例如“UTF-8”:item.getString( "UTF-8" ).
【解决方案2】:

您需要确保目标控制台/文件/数据库/无论您在哪里打印/写入/插入文件名以支持 UTF-8。问号表示它未配置为接受 UTF-8,并且目标本身知道这一点。否则你只会看到mojibake

由于问题中缺少有关目标的详细信息,我只能建议通过this article 了解幕后角色的情况。

【讨论】:

  • 你说得对,我没有提供显示目标的信息。好吧,我在 Eclipse 的变量视图中调试时看到了问号(在我的程序中所有特殊字符都可以),也在 log4j 日志文件中,在插入这些名称的数据库中,最后当文件下载回客户端时.
  • 我总是从调试开始检查这些问题。如果我可以在我的监视窗口中看到正确的字符串,那么就很容易找到错误的地方。然而,在这种情况下,当我得到我的文件名时,它是不正确的。
  • 据我了解,浏览器会在 HTTP 标头中告知其消息的编码。解析请求时,应使用此编码。 Apache javadoc 还对 ServletFileUpload.setHeaderEncoding 说:“如果未指定或为空,则使用请求编码。”在我的情况下 enc = request.getCharacterEncoding();导致“UTF-8”,所以我认为这是浏览器发送的。但是为什么解析器无法获得正确的文件名呢..? :-(
  • 从更改 Eclipse 工作区编码开始:Window > Preferences > General > Workspace文本文件编码设置为 UTF-8
【解决方案3】:

通过显式调用 ServletFileUpload 实例的 .setHeaderEncoding("ISO-8858-2") 解决了问题。

【讨论】:

  • 使用 ISO-8859-2 代替 Java 不支持的 ISO-8858-2:docs.oracle.com/javase/7/docs/technotes/guides/intl/…;我们在使用 ISO-8858-2 编码时遇到了 java.io.UnsupportedEncodingException: ISO-8858-2。 DiskFileUpload 上传 = new DiskFileUpload(); upload.setHeaderEncoding("ISO-8859-2")
【解决方案4】:

对于这些特殊字符,您可以将编码设置为“iso 8859-1”。 UTF-8 似乎无法正常工作..

如果你没有设置任何编码类型..那么linux机器将采用默认编码,即UTF-8,windows将采用兼容编码

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-25
    • 2013-06-27
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    相关资源
    最近更新 更多