【问题标题】:Java for Web - Multipart/form-data file with wrong encodingJava for Web - 编码错误的多部分/表单数据文件
【发布时间】:2016-12-06 01:11:48
【问题描述】:

我正在使用 Java 和 Tomcat 8 开发一个 Web 应用程序。该应用程序有一个用于上传文件的页面,该文件的内容将显示在不同的页面中。很简单。

但是,这些文件可能包含不常见的字符作为其文本的一部分。例如,现在,我正在处理一个包含越南语文本的文件。

文件以 UTF-8 编码,可以在任何文本编辑器中打开。但是,尽管进行了很多搜索并尝试了许多不同的方法,但我找不到任何方法来上传它并将内容保持在正确的编码中。

我上传文件的页面包含以下表格:

<form method="POST" action="upload" enctype="multipart/form-data" accept-charset="UTF-8" >
                                File: <input type="file" name="file" id="file"  multiple/><br/>
                                Param1: <input type="text" name="param1"/> <br/>
                                Param2: <input type="text" name="param2"/> <br/>
                                <input type="submit" value="Upload" name="upload" id="upload" />
                            </form>

它还包含:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
...
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

我的 servlet 如下所示:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            response.setContentType("text/html;charset=UTF-8");
            request.setCharacterEncoding("UTF-8");

            String param1 = request.getParameter("param1");

            String param2 = request.getParameter("param2");

            Collection<Part> parts = request.getParts();

            Iterator<Part> iterator = parts.iterator();
            while (iterator.hasNext()) {
                Part filePart = iterator.next();
                InputStream filecontent = null;

                filecontent = filePart.getInputStream();

                String content = convertStreamToString(filecontent, "UTF-8");

                //Save the content and the parameters in the database

                if (filecontent != null) {
                    filecontent.close();
                }
            }

        } catch (ParseException ex) {
        } 
    }

static String convertStreamToString(java.io.InputStream is, String encoding) {
        java.util.Scanner s = new java.util.Scanner(is, encoding).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

尽管我付出了所有努力,但我始终无法获得保留正确字符的“内容”字符串。当正确的应该是“Kạn”时,我要么得到类似“K?n”或“Kạn”的东西(这似乎是 ISO-8859-1 的解释)。

更糟糕的是,如果我在其他表单参数(param1 或 param2)中写入越南字符,这也需要是可能的,如果我同时设置表单的接受字符集和 servlet,我只能正确读取它们扫描仪编码为 ISO-8859-1,我绝对不明白。在这种情况下,如果我打印接收到的参数,我会得到类似“K & # 7 8 4 1 ; n”(不带空格)的内容,其中包含正确字符的表示。因此,只要表单本身使用该字符集,似乎可以使用 ISO-8859-1 从表单中读取越南语字符。但是,它永远不会对上传文件的内容起作用。我什至尝试在 ISO-8859-1 中对文件进行编码,以便对所有内容使用字符集,但它根本不起作用。

我相信这种情况并不少见,所以我想向以前可能去过那里的人寻求帮助。我可能遗漏了一些东西,所以任何帮助表示赞赏。

提前谢谢你。


编辑1:虽然这个问题还没有收到回复,但我会继续发布我的发现,以防有人感兴趣或关注它。

在尝试了许多不同的事情之后,我似乎已经缩小了问题的原因。我创建了一个类,它从磁盘中的特定文件夹读取文件并打印其内容。代码如下:

public static void openFile() {
    System.out.println(String.format("file.encoding: %s", System.getProperty("file.encoding")));
    System.out.println(String.format("defaultCharset: %s", Charset.defaultCharset().name()));

    File file = new File(myFilePath);
    byte[] buffer = new byte[(int) file.length()];
    BufferedInputStream f = null;
    String content = null;
    try {
        f = new BufferedInputStream(new FileInputStream(file));
    } catch (FileNotFoundException ex) {
    }

    try {
        f.read(buffer);
        content = new String(buffer, "UTF-8");
        System.out.println("UTF-8 File: " + content);
        f.close();
    } catch (IOException ex) {
    }
}

然后我向这个类添加了一个主函数,使其可执行。当我独立运行它时,我得到以下输出:

文件编码:UTF-8
默认字符集:UTF-8
UTF-8 文件:{"...Kạn..."}

但是,如果按照应有的方式将项目作为 web 应用程序运行,并从该类调用相同的函数,我会得到:

file.encoding: Cp1252
默认字符集:windows-1252
UTF-8 文件:{"...K?n..."}

当然,这清楚地表明 webapp 用于读取文件的默认编码不是 UTF-8。因此,我对该主题进行了一些研究,并找到了为 Tomcat 创建 setenv.bat 并让它执行的经典答案:

set "JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8"

结果还是不对:

文件编码:UTF-8
默认字符集:UTF-8
UTF-8 文件 {"...Kạn..."}

我现在可以看到默认编码变成了 UTF-8。但是,从文件中读取的内容仍然是错误的。上面显示的内容与我在 Microsoft Word 中打开文件时得到的内容相同,但选择使用 ISO-Latin-1 而不是 UTF-8 读取它。出于某种奇怪的原因,读取文件仍然在某处使用 ISO-Latin-1,尽管一切都表明使用 UTF-8。

再次,如果有人对此有建议或指导,我们将不胜感激。

【问题讨论】:

    标签: java tomcat utf-8 character-encoding multipartform-data


    【解决方案1】:

    我似乎无法结束这个问题,所以让我贡献一下我找到的答案。

    问题在于调查这类问题非常棘手,因为代码中有很多地方可能会更改编码(页面、表单编码、请求编码、文件读取、文件写入、控制台输出,数据库写入,数据库读取......)。

    就我而言,在完成了我在问题中发布的所有内容之后,我浪费了很多时间来尝试解决不再存在的问题,因为我的 IDE 中的控制台输出(NetBeans,用于该项目) 没有使用所需的字符编码。所以我在一定程度上做的一切都是正确的,但是当我试图打印任何东西时,我会弄错。在我开始将日志写入文件而不是控制台,从而控制写入编码之后,我开始清楚地理解这个问题。

    在我已经在问题中描述的所有内容之后(在编辑之前),我的解决方案中缺少的是为数据库连接配置编码。令我惊讶的是,即使我的数据库和所有表都使用 UTF-8,应用程序和 MySQL 之间的通信仍然使用 ISO-Latin。最后缺少的是将“useUnicode=true&characterEncoding=utf-8”添加到连接中,就像这样:

    con = DriverManager.getConnection("jdbc:mysql:///dbname?useUnicode=true&characterEncoding=utf-8", "user", "pass");
    

    感谢这个答案,其中包括:https://stackoverflow.com/a/3275661/843668

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多