JSP SmartUpload上傳檔案亂碼解決紀實+UploadBean上傳解決方案
來源:互聯網
上載者:User
js|解決|上傳 作者:fbysss
聲明:本文為fbysss原創,如需引用,請註明作者及引用地址
關鍵字:smartupload,uploadbean,linux,中文亂碼
一、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:jameslastchina@hotmail.com
//==========================================================================
-->
<%@ 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