2016-08-01 72 views
0

我正在開發使用Java和Tomcat 8. Web應用程序此應用程序上傳與將在不同的頁面中給出的內容的文件頁面的multipart/form-data的文件。平原簡單。的Java的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」(這似乎是ISO-8859-1的解釋),正確的時候應該是「Kạn」。

如果我在其他表單參數(param1或param2)中寫入越南語字符(這也是可能的),那麼我只能正確讀取它們,如果我將表單的accept-charset和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) { 
    } 
} 

然後我給這個類添加了一個主函數,使它可執行。當我運行它的獨立,我得到下面的輸出:

的file.encoding:UTF-8
defaultCharset:UTF-8
UTF-8文件:{」 ... ...侃「}

但是,如果運行該項目作爲一個Web應用程序,因爲它應該是,並從該類調用同一個函數,我得到:

的file.encoding:
的Cp1252 defaultCharset:窗口1252
UTF-8文件:{ 「?...,K N ...」。}

。當然,這是充分顯示出由Web應用程序使用的默認編碼讀取文件不是UTF-8,所以我做了一些研究主題和發現創建Tomcat上setenv.bat並讓它執行的經典回答:

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

的結果,但是,仍然是不對的:

的file.encoding:UTF-8
defaultCharset:UTF-8
UTF-8文件{ 「......Kạn......」}

我現在默認的編碼成了UTF-8看看。然而,從文件中讀取的內容仍然是錯誤的。上面顯示的內容與我在Microsoft Word中打開文件時得到的內容相同,但選擇使用ISO-Latin-1而不是UTF-8讀取它。出於某種奇怪的原因,讀取文件仍然可以在某個地方使用ISO-Latin-1,儘管所有內容都指出使用UTF-8。

再次,如果有人可能有這方面的建議或指示,將不勝感激。

回答

0

我似乎無法關閉該問題,因此讓我以我找到的答案作出貢獻。

問題是,調查這種類型的問題非常棘手,因爲代碼中有很多點可能會改變編碼(頁面,表單編碼,請求編碼,文件讀取,文件寫入,控制檯輸出,數據庫寫入,數據庫讀取......)。

就我而言,在完成我在問題中發佈的所有內容之後,我花了很多時間試圖解決不再存在的問題,僅僅是因爲IDE中的控制檯輸出(NetBeans,爲此項目)沒有使用所需的字符編碼。所以我一直在做一切正確的事情,但是當我試圖打印任何內容時,我會錯誤的。在我開始將日誌寫入文件而不是控制檯之後,從而控制寫入編碼之後,我開始清楚地理解問題。

在我的問題(在編輯之前)中已經描述的所有內容之後,我的解決方案中缺少的是配置數據庫連接的編碼。令我驚訝的是,即使我的數據庫和我的所有表都在使用UTF-8,應用程序和MySQL之間的通信依然採用ISO-Latin。唯一缺少的最後一件事是加入「了useUnicode =真&的characterEncoding = UTF-8」的連接,就像這樣:

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

多虧了這個答案,以及很多其他:https://stackoverflow.com/a/3275661/843668