一、SmartUpload上傳文件亂碼解決紀實

一、SmartUpload上傳文件亂碼解決紀實
      噁心指數:五星
      完成程度:80%(文件名問題未解決)

      問題描述:在windows下開發的web應用,用到了smartupload上傳文件,需求很簡單,就是一個表單文件formdata.jsp,一個獲取表單並上傳的文件getdata.jsp,調試的時候,windows和linux系統下均正常,當系統安裝到另一臺服務器的時候,卻出現了獲取表單參數值爲亂碼(全是問號???)的問題。
       我腦子裏面第一感覺是:兩臺機器,據同事說是同一張光盤安裝的Linux,但我想,根據邏輯推斷,肯定是這liux裝得不一樣,或者是相關的服務不一樣。否則怎麼可能呢?然而,上頭任務交給我來解決了,而且系統馬上要正式使用,如果我要求重新安裝Linux,幾乎是不可能的。那好,我不入地獄,誰入地獄?我就闖它一把。
      其實在這個時候,我還認爲問題不大的。因爲java開發的東西,亂碼問題是家常便飯,而解決辦法也就是那幾種。不就一個轉碼嗎?當時頭兒問我問題大不大,我說,應該沒啥大問題。
我開始進行getByte()轉碼,用ISO-8859-1 與gb312/GBK”互相轉換,未果,又加入UTF-8,不行;
又在<%@ page contentType="text/html;charset=gb2312">進行編碼替換,不行;
修改linux LANG=zh_CN.GB2312,不行;
修改web.xml的charset,不行;

        此時我幾乎已經查遍了所有有關的網頁,而且找到這問題和smartupload有關。但解決的人寥寥無幾,而且解決的辦法也很不詳細,於是在csdn上發帖,結果半天沒人理會,頂都沒人頂。再上開發羣上問,大家都忙,也無暇顧及。繼續自己調試,用System.getProperty(“file.encoding”)得到的結果是ANSI_X3.4-1968,這是個什麼碼?上google查了一下,全是些無用信息,此時我心裏不禁有些發冷。。。NND,問題有些嚴重。。
        當天到下班,我是沒啥結果,已經頭昏腦脹,不想加班了,但花大半天時間還沒搞定這麼一個“小問題”,實在是有些沒面子,於是我向頭兒保證,明天我一定解決。
        回到屋裏,茶不思飯不香。上QQ看看,跟一MM聊了幾句,我說今天好累,她說我明天可以好好休息一下。啊?明天星期幾?我一覈實,靠,明天週六啊!看來老天註定要我週末加班了。
        晚上沒睡好,起來又是一頓查,還是沒啥好辦法。
        第二天,11點才起牀,起來煮碗麪條就開始幹,把那些編碼用new String(str.getByte(“iso-8859-1“),“gbk“)這樣的形式進行了若干中組合,不行,怎麼辦,看到有一個改smartupload源碼的解決辦法,我是很不想改源碼的,因爲服務器在遠程,我沒有root帳號,修改了類無法重啓。
        進展一:把formdata.jsp中<%@ page contentType="text/html;charset=gb2312">,取掉,加上<meta http-equiv="Content-Type" content="text/html; charset=gb2312">,獲取頁面轉碼後能夠正常顯示中文。但是,大家都知道,這樣做的後果是什麼,formdta.jsp無法顯示中文!這個問題更難做了,而且用response.setContentType居然對頁面沒有任何作用,真邪門了。
        時間一點點過去,我終於動搖了,我開始試着去記憶root的密碼,試了一下,我靠居然是對的。OK,終於可以大展拳腳了。
        然而,smartupload的源碼,居然很不好找,搜了半天沒有。只好反編譯了。用gel反編譯出來的結果跟別人說的還不一樣,就湊合着改了一下,
找到SmartUpload.java中的    public void upload(),加一個參數String charsetName,
找到這句 String s11 = new String(m_binArray, m_startData, (m_endData - m_startData) + 1);
修改爲String s11 = new String(m_binArray, m_startData, (m_endData - m_startData) + 1,charsetName);
編譯後上傳,重啓再試,發現有了一點進展。
        進展二:部分參數能夠正確讀取了!
        這只是表單文本框傳值可以了,可文件名依然是亂碼,我又折騰了半天,實在不想再去弄那個smartupload的源碼了,雖然代碼不多,但是我這麼弄也太花時間了。(注:我覺得改源碼應該可以解決問題,只是沒有改完,文件名那部分需要進行處理。有興趣的可以試試)

        這時自然想到了換其他的上傳包,搜了一下,有人說javazoom的不錯,搞一個下來再說,demo很簡單,
測試之後發現,只要在接收頁面getdata.jsp中轉碼就可以了。轉碼方式,可以是一個個參數單獨轉,也可以用一句話就可以:request.setCharacterEncoding("GBK");同時要配合
MultipartFormDataRequest(request,null,100*1024*1024,MultipartFormDataRequest.COSPARSER,"GBK");
這個uploadbean的做的非常體貼,居然提供一個ChineseUpload.jsp例子,其實主要就是上面兩句話不同。
        等我修改完,感覺差不多的時候,已經是深夜2點。想放鬆了,先睡再說。
       週日,繼續工作,發現一個新問題,uploadbean居然不能修改上傳的文件名!這怎麼行呢?是有一種變通方法,每個文件建立一個目錄,然後放進去防止重名,但這有點噁心,而且直接進去的文件名還是亂碼,這可咋整啊???
       還好,我再次發現了UploadBean的優越性,我找到了一個帖子,說UploadBean1.5配合Filemover可以改名,於是又下了1.5和FileMover,FileMover中的例子也很詳細簡單。真是貼心。。。
       修改,上傳重啓,一切OK!
       後來,又發現系統的幾個相關BUG,一鼓作氣,全部解決。

       這個“小問題”,居然花了我整整兩天的時間,可謂令我惱怒!同時,也想到跟我同樣痛苦的兄弟們,我能減輕一下你們的痛苦,我這兩天就沒白乾!我現在的口號是:“放棄SmartUpload,全面使用UploadBean”。我還寫了一個Demo,以幫助痛苦的兄弟們快速解決問題。
       下面,我把我寫的Demo和需要的資料鏈接都貼在這裏,大家有什麼問題可以在這裏跟我交流。

二、UploadBean上傳解決方案
    滿意指數:五星
    完成程度:100%
 Demo:
1.表單頁面sssformdata.jsp
<%@ page contentType="text/html;charset=gb2312"  %>
<head>
<title>fbysss UploadBean 示例</title>
<!--meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"-->
<!--meta http-equiv="Content-Type" content="text/html; charset=gb2312"-->
</head>
<FORM   name="form1" METHOD="POST" ACTION="sssupload.jsp" ENCTYPE="multipart/form-data">
      <input name="title" type= "text" value="中文字">
      <td class="bodystyle">附件</td>
      <td class="bodystyle"> <input name="attach" type="FILE" id="attach" size="50" > </td>
      <input name="ok" type= "submit" value="提交">
</form>

2.讀取表單頁面sssgetdata.jsp
<!--
 //==========================================================================
 //文件:UploadBean上傳實例
 //功能:解決中文亂碼,完成文件上傳,並提供上傳改名解決方案
 //作者:fbysss
 //msn:[email protected]
 //==========================================================================
-->
<%@ page contentType="text/html;charset=GBK" %>
<%@ page language="java" import="com.jspsmart.upload.*"%>
<%@ page import="java.text.SimpleDateFormat"%>
<%@ page import="java.io.File"%>
<%@ page import="java.util.*"%>
<%@ page import="javazoom.upload.*"%>
<%@ page import="uploadutilities.FileMover"%>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<% 
      request.setCharacterEncoding("GBK");//設置編碼格式,就不用一個個轉碼了。
      FileMover fileMover = new FileMover();//你也可以使用自帶的實例中jsp:useBean的形式。
   UploadBean upBean = new UploadBean();
      MultipartFormDataRequest mrequest = null;
   Hashtable files = null;
  
   if (MultipartFormDataRequest.isMultipartFormData(request))
      {

   mrequest = new MultipartFormDataRequest(request,null,100*1024*1024,MultipartFormDataRequest.COSPARSER,"GBK");//注意這裏也要設置編碼參數
     String sTt0 = mrequest.getParameter("title");
     out.println("<br>Title0是:"+sTt0+"<br>");
     String sTt1 = new String(sTt0.getBytes("ISO-8859-1"),"GBK");
     out.println("<br>Title1是:"+sTt1+"<br>");
     //這裏用來測試title參數是否正確。調試的時候,加一句if (true)return;即可。
         files = mrequest.getFiles();
   }


 //獲取修改前的文件名
 String sOldFileName =mrequest.getParameter("oldfilename");
 out.println("sOldFileName:"+sOldFileName);
 String sWebRootPath = request.getRealPath("/");//得到你的web應用的根。
 String sPath=sWebRootPath+"attach";
 int iFileCount = 0;
 String sServerFileName="";
 String sLocalFileName = "";
 //文件獲取
 if ( (files != null) || (!files.isEmpty()) ) {
 
  iFileCount = files.size();
  UploadFile file = (UploadFile) files.get("attach");
  sLocalFileName=file.getFileName();
  out.println("sLocalFileName:"+sLocalFileName);
  int ii= sLocalFileName.indexOf("."); //取文件名的後綴
  String sExt = sLocalFileName.substring(ii,sLocalFileName.length());
  //得到不重複的文件名
  java.util.Date dt = new java.util.Date(System.currentTimeMillis());
  SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
  sServerFileName= fmt.format(dt);
  sServerFileName =sServerFileName + sExt;
  //如果不存在該目錄,則新建一個
  File dir =new File(sPath);
  if (!dir.exists()){
   dir.mkdirs();
  }
  upBean.setFolderstore(sPath);//設置要上傳的目錄
  upBean.addUploadListener(fileMover);//增加filMover監聽
  fileMover.setNewfilename(sServerFileName);//設置服務器上的文件名
  upBean.store(mrequest, "attach");//上傳
  out.println("file path is "+sPath+"/"+sServerFileName);
 }

%>

Demo注意事項:cos.jar,uploadbean.jar,filemover.jar這幾個包必須有。
必備下載地址:
UploadBean1.5:http://wcarchive.cdrom.com/pub/simtelnet/winnt/java/uploadbean1_5.zip
FileMover1.3:http://www.javazoom.net/jzservlets/uploadbean/addons/filemover1.3.zip
參考下載地址:
ChinesUpload例子:http://www.javazoom.net/jzservlets/uploadbean/addons/ChineseUpload.zip
作者:fbysss
聲明:本文爲fbysss原創,如需引用,請註明作者及引用地址
關鍵字:smartupload,uploadbean,linux,中文亂碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章