日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WEB文件上传之apache common upload使用(一)

發布時間:2023/12/10 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WEB文件上传之apache common upload使用(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文件上傳一個經常用到的功能,它有許多中實現的方案。

頁面表單 + RFC1897規范 + http協議上傳

頁面控件(flash/html5/activeX/applet) + RFC1897規范 + http協議上傳

頁面控件(flash/html5/activeX/applet) + 自定義數據規范 + http協議上傳

頁面控件(flash/html5/activeX/applet) + FTP協議上傳

頁面控件(flash/html5/activeX/applet) + 自定義協議

?

? 用apache common upload組件實際就是采用的“頁面表單 + RFC1897規范 + http協議上傳”實現方式,需要實現的技術點:

1. 多文件數據的提交

2. 文件數據包接收存儲功能

3. 文件數據上傳進度

4.?WEB頁面無刷新異步提交

?

?時序圖:

  • 文件上傳時序圖


  • 文件上傳進度獲取時序圖

實現思路:

1. 多文件數據的提交

在WEB頁面采用多個<input type="file">利用form表單進行文件提交

?

2. 文件數據包接收存儲功能

服務端采用servlet,利用apache common upload組件接收解析數據包,接收解析的過程中保存進度到session, 文件接收完畢后保存到指定目錄

?

3. 文件數據上傳進度

在WEB頁面在界面寫一個定時器,定時訪問服務器提供上傳進度獲取功能的servlet,獲取文件上傳進度信息

?

4. WEB頁面無刷新異步提交

利用iframe來實現WEB頁面無刷新異步上傳

?

關鍵代碼:

UploadFileServlet.java

Java代碼?

?

  • package?com.test.servlet;??
  • ??
  • import?java.io.File;??
  • import?java.io.IOException;??
  • import?java.io.Writer;??
  • import?java.util.Iterator;??
  • import?java.util.List;??
  • ??
  • import?javax.servlet.ServletException;??
  • import?javax.servlet.http.HttpServlet;??
  • import?javax.servlet.http.HttpServletRequest;??
  • import?javax.servlet.http.HttpServletResponse;??
  • ??
  • import?org.apache.commons.fileupload.FileItem;??
  • import?org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;??
  • import?org.apache.commons.fileupload.disk.DiskFileItemFactory;??
  • import?org.apache.commons.fileupload.servlet.FileCleanerCleanup;??
  • import?org.apache.commons.fileupload.servlet.ServletFileUpload;??
  • import?org.apache.commons.io.FileCleaningTracker;??
  • import?org.apache.commons.io.FileUtils;??
  • import?org.apache.commons.io.FilenameUtils;??
  • import?org.apache.commons.io.IOUtils;??
  • import?org.apache.commons.lang3.ArrayUtils;??
  • import?org.apache.commons.logging.Log;??
  • import?org.apache.commons.logging.LogFactory;??
  • ??
  • /**?
  • ?*?文件上傳數據接收類?
  • ?*??
  • ?*?@author?chengqi?
  • ?*?
  • ?*/??
  • public?class?UploadFileServlet?extends?HttpServlet?{??
  • ??
  • ????/**?日志對象*/??
  • ????private?Log?logger?=?LogFactory.getLog(this.getClass());??
  • ??
  • ????private?static?final?long?serialVersionUID?=?1L;??
  • ??
  • ????/**?上傳目錄名*/??
  • ????private?static?final?String?uploadFolderName?=?"uploadFiles";??
  • ??
  • ????/**?上傳臨時文件存儲目錄*/??
  • ????private?static?final?String?tempFolderName?=?"tempFiles";??
  • ??
  • ????/**?上傳文件最大為30M*/???
  • ????private?static?final?Long?fileMaxSize?=?30000000L;???
  • ??
  • ????/**?允許上傳的擴展名*/??
  • ????private?static?final?String?[]?extensionPermit?=?{"txt",?"xls",?"zip"};??
  • ??
  • ????/**?統一的編碼格式*/??
  • ????private?static?final?String?encode?=?"UTF-8";??
  • ??
  • ????@Override??
  • ????protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{??
  • ????????logger.info("UploadFileServlet#doPost()?start");??
  • ????????try?{??
  • ????????????String?curProjectPath?=?this.getServletContext().getRealPath("/");??
  • ????????????String?saveDirectoryPath?=?curProjectPath?+?"/"?+?uploadFolderName;??
  • ????????????String?tempDirectoryPath?=?curProjectPath?+?"/"?+?tempFolderName;??
  • ????????????File?saveDirectory?=?new?File(saveDirectoryPath);??
  • ????????????File?tempDirectory?=?new?File(tempDirectoryPath);??
  • ????????????logger.debug("Project?real?path?["?+?saveDirectory.getAbsolutePath()?+?"]");??
  • ????????????//上傳時產生的臨時文件的默認保存目錄??
  • ????????????logger.debug("Temp?files?default?save?path?["?+?System.getProperty("java.io.tmpdir")?+?"]");??
  • ????????????DiskFileItemFactory?factory?=?new?DiskFileItemFactory();??
  • ????????????//DiskFileItemFactory中DEFAULT_SIZE_THRESHOLD=10240表示如果上傳文件大于10K則會產生上傳臨時文件??
  • ????????????//上傳臨時文件的默認目錄為java.io.tmpdir中保存的路徑,根據操作系統的不同會有區別??
  • ??????????????
  • ????????????if(!tempDirectory.exists())?{??
  • ????????????????tempDirectory.mkdir();??
  • ????????????}??
  • ????????????//重新設置臨時文件保存目錄??
  • ????????????factory.setRepository(tempDirectory);??
  • ??
  • ????????????//設置文件清除追蹤器,文件上傳過程中產生的臨時文件會在??
  • ????????????FileCleaningTracker?fileCleaningTracker?=?FileCleanerCleanup.getFileCleaningTracker(this.getServletContext());??
  • ????????????factory.setFileCleaningTracker(fileCleaningTracker);??
  • ??
  • ????????????ServletFileUpload?upload?=?new?ServletFileUpload(factory);??
  • ??
  • ????????????//設置文件上傳進度監聽器??
  • ????????????FileProcessListener?processListener?=?new?FileProcessListener(request.getSession());??
  • ????????????upload.setProgressListener(processListener);??
  • ??
  • ????????????//?設置文件上傳的大小限制??
  • ????????????upload.setFileSizeMax(fileMaxSize);??
  • ??
  • ????????????//?設置文件上傳的頭編碼,如果需要正確接收中文文件路徑或者文件名??
  • ????????????//?這里需要設置對應的字符編碼,為了通用這里設置為UTF-8??
  • ????????????upload.setHeaderEncoding(encode);??
  • ??
  • ????????????//解析請求數據包??
  • ????????????List<FileItem>?fileItems?=?upload.parseRequest(request);??
  • ????????????//遍歷解析完成后的Form數據和上傳文件數據??
  • ????????????for?(Iterator<FileItem>?iterator?=?fileItems.iterator();?iterator.hasNext();)?{??
  • ????????????????FileItem?fileItem?=?iterator.next();??
  • ????????????????String?fieldName?=?fileItem.getFieldName();??
  • ????????????????String?name?=?fileItem.getName();??
  • ????????????????//如果為上傳文件數據??
  • ????????????????if(!fileItem.isFormField())?{??
  • ????????????????????logger.debug("fieldName["?+?fieldName?+?"]?fileName["?+?name?+?"]?");??
  • ????????????????????if(fileItem.getSize()?>?0)?{??
  • ????????????????????????String?fileExtension?=?FilenameUtils.getExtension(name);??
  • ????????????????????????if(!ArrayUtils.contains(extensionPermit,?fileExtension))?{??
  • ????????????????????????????throw?new?NoSupportExtensionException("No?Support?extension.");??
  • ????????????????????????}??
  • ????????????????????????String?fileName?=?FilenameUtils.getName(name);??
  • ????????????????????????FileUtils.copyInputStreamToFile(fileItem.getInputStream(),???
  • ????????????????????????????????new?File(saveDirectory,?fileName));??
  • ????????????????????}??
  • ????????????????}?else?{?//Form表單數據??
  • ????????????????????String?value?=?fileItem.getString(encode);??
  • ????????????????????logger.debug("fieldName["?+?value?+?"]?fieldValue["?+?fieldName?+?"]");??
  • ????????????????}??
  • ????????????}??
  • ????????????responseMessage(response,?State.OK);??
  • ????????}?catch(FileSizeLimitExceededException?e)?{???
  • ????????????logger.error(e.getMessage(),?e);??
  • ????????????responseMessage(response,?State.OVER_FILE_LIMIT);??
  • ????????}?catch(NoSupportExtensionException?e)?{???
  • ????????????logger.error(e.getMessage(),?e);??
  • ????????????responseMessage(response,?State.NO_SUPPORT_EXTENSION);??
  • ????????}?catch(Exception?e)?{??
  • ????????????logger.error(e.getMessage(),?e);??
  • ????????????responseMessage(response,?State.ERROR);??
  • ????????}?finally?{??
  • ????????????//清除上傳進度信息??
  • ????????????request.getSession().removeAttribute("fileUploadProcess");??
  • ????????}??
  • ????????logger.info("UploadFileServlet#doPost()?end");???
  • ????}??
  • ??
  • ????public?enum?State?{??
  • ????????OK(200,?"上傳成功"),??
  • ????????ERROR(500,?"上傳失敗"),??
  • ????????OVER_FILE_LIMIT(501,?"超過上傳大小限制"),??
  • ????????NO_SUPPORT_EXTENSION(502,?"不支持的擴展名");??
  • ??
  • ????????private?int?code;??
  • ????????private?String?message;??
  • ????????private?State(int?code,?String?message)?{??
  • ????????????this.code?=?code;??
  • ????????????this.message?=?message;??
  • ????????}??
  • ??
  • ????????public?int?getCode()?{??
  • ????????????return?code;??
  • ????????}??
  • ????????public?String?getMessage()?{??
  • ????????????return?message;??
  • ????????}??
  • ??
  • ????}??
  • ??
  • ????/**?
  • ?????*?返回結果函數?
  • ?????*?@param?response?
  • ?????*?@param?state?
  • ?????*/??
  • ????private?void?responseMessage(HttpServletResponse?response,?State?state)?{??
  • ????????response.setCharacterEncoding(encode);??
  • ????????response.setContentType("text/html;?charset="?+?encode);??
  • ????????Writer?writer?=?null;??
  • ????????try?{??
  • ????????????writer?=?response.getWriter();??
  • ????????????writer.write("<script>");??
  • ????????????writer.write("window.parent.fileUploadCallBack({\"code\":"?+?state.getCode()?+",\"message\":\""?+?state.getMessage()+?"\"});");??
  • ????????????writer.write("</script>");??
  • ????????????writer.flush();??
  • ????????????writer.close();??
  • ????????}?catch(Exception?e)?{??
  • ????????????logger.error(e.getMessage(),?e);??
  • ????????}?finally?{??
  • ????????????IOUtils.closeQuietly(writer);??
  • ????????}??
  • ????}??
  • ??
  • ??
  • }??
  • ??

    ?

    GetFileProcessServlet.java

    Java代碼?

    ?

  • package?com.test.servlet;??
  • ??
  • import?java.io.IOException;??
  • import?java.io.Writer;??
  • ??
  • import?javax.servlet.ServletException;??
  • import?javax.servlet.http.HttpServlet;??
  • import?javax.servlet.http.HttpServletRequest;??
  • import?javax.servlet.http.HttpServletResponse;??
  • ??
  • import?org.apache.commons.io.IOUtils;??
  • import?org.apache.commons.logging.Log;??
  • import?org.apache.commons.logging.LogFactory;??
  • ??
  • /**?
  • ?*?文件上傳進度獲取Servlet?
  • ?*??
  • ?*?@author?chengqi?
  • ?*?
  • ?*/??
  • public?class?GetFileProcessServlet?extends?HttpServlet?{??
  • ??
  • ????/**?日志對象*/??
  • ????private?Log?logger?=?LogFactory.getLog(this.getClass());??
  • ??
  • ????private?static?final?long?serialVersionUID?=?1L;??
  • ??
  • ????@Override??
  • ????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)??
  • ????????????throws?ServletException,?IOException?{??
  • ????????logger.info("GetFileProcessServlet#doGet?start");??
  • ????????String?fileUploadPercent?=?(String)request.getSession().getAttribute("fileUploadProcess");??
  • ????????Writer?writer?=?null;??
  • ????????try?{??
  • ????????????writer?=?response.getWriter();??
  • ????????????logger.info("percent:"?+?fileUploadPercent);??
  • ????????????IOUtils.write(fileUploadPercent?==?null???"0%"?:?fileUploadPercent,?writer);??
  • ????????????writer.flush();??
  • ????????????writer.close();??
  • ????????}?catch(Exception?e)?{??
  • ????????????logger.error(e.getMessage(),?e);??
  • ????????}?finally?{??
  • ????????????IOUtils.closeQuietly(writer);??
  • ????????}??
  • ????????logger.info("GetFileProcessServlet#doGet?end");??
  • ????}??
  • ??
  • }??
  • ?

    FileProcessListener.java

    Java代碼?

    ?

  • package?com.test.servlet;??
  • ??
  • import?java.text.NumberFormat;??
  • ??
  • import?javax.servlet.http.HttpSession;??
  • ??
  • import?org.apache.commons.fileupload.ProgressListener;??
  • import?org.apache.commons.logging.Log;??
  • import?org.apache.commons.logging.LogFactory;??
  • ??
  • /**?
  • ?*?文件進度監聽器?
  • ?*??
  • ?*?@author?chengqi?
  • ?*?
  • ?*/??
  • public?class?FileProcessListener?implements?ProgressListener{??
  • ??
  • ????/**?日志對象*/??
  • ????private?Log?logger?=?LogFactory.getLog(this.getClass());??
  • ??
  • ????private?HttpSession?session;??
  • ??
  • ????public?FileProcessListener(HttpSession?session)?{??
  • ????????this.session?=?session;????
  • ????}??
  • ??????
  • ??
  • ????public?void?update(long?pBytesRead,?long?pContentLength,?int?pItems)?{??
  • ????????double?readByte?=?pBytesRead;??
  • ????????double?totalSize?=?pContentLength;??
  • ????????if(pContentLength?==?-1)?{??
  • ????????????logger.debug("item?index["?+?pItems?+?"]?"?+?pBytesRead?+?"?bytes?have?been?read.");??
  • ????????}?else?{??
  • ????????????logger.debug("item?index["?+?pItems?+?"]?"?+?pBytesRead?+?"?of?"?+?pContentLength?+?"?bytes?have?been?read.");??
  • ????????????String?p?=?NumberFormat.getPercentInstance().format(readByte?/?totalSize);??
  • ????????????session.setAttribute("fileUploadProcess",?p);??
  • ????????}??
  • ????}??
  • ??
  • }??
  • ?

    ?

    apacheUploadDemo.html

    ?

    Html代碼?

    ?

  • <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"?"http://www.w3.org/TR/html4/loose.dtd">??
  • <html>??
  • <head>??
  • ????<title>Apache?common實現基本文件上傳</title>??
  • ????<meta?http-equiv="Content-Type"?content="text/html;?charset=UTF-8">??
  • ????<script?type="text/javascript"?src="js/jquery/jquery-1.9.1.js"></script>??
  • ????<script?type="text/javascript"?src="js/jquery/jquery.form.js"></script>??
  • ????<script?type="text/javascript">??
  • ??
  • ????//定時器對象??
  • ????var?uploadProcessTimer?=?null;??
  • ??
  • ????$(function?(){??
  • ????????//綁定定時器開始操作到提交按鈕??
  • ????????$('input[type=submit]').click(function?()?{??
  • ????????????//啟動上傳進度查詢定時器??
  • ????????????uploadProcessTimer?=?window.setInterval(getFileUploadProcess,?20);??
  • ????????})??
  • ????});??
  • ??
  • ????//獲取文件上傳進度??
  • ????function?getFileUploadProcess()?{??
  • ????????$.get('/upload/getFileProcessServlet',?function(data)?{??
  • ????????????$('#fileUploadProcess').html(data);??
  • ????????});??
  • ????}??
  • ??
  • ????//上傳完成后,由iframe返回腳本自動調用??
  • ????function?fileUploadCallBack(res)?{??
  • ????????//清除定時器??
  • ????????if(uploadProcessTimer)?{??
  • ????????????window.clearInterval(uploadProcessTimer);??
  • ????????}??
  • ????????var?message?=?res['message'];??
  • ????????var?code?=?res['code'];??
  • ????????if(code?!=?200)?{??
  • ????????????$('#fileUploadProcess').html('0%');??
  • ????????}??
  • ????????alert(message);??
  • ????}??
  • ??
  • ????</script>??
  • </head>??
  • <body>??
  • <h2>上傳文件1</h2>??
  • ??
  • 用戶信息:??<br/>??
  • <form?id="testForm"?action="/upload/uploadServlet"?method="post"?enctype="multipart/form-data"?target="iframeUpload">??
  • ????姓名:<input?name="name"?type="text">?<br/>??
  • ????附件1:<input?name="file1"?type="file"?>?<br/>??
  • ????附件2:<input?name="file2"?type="file"?>?<br/>??
  • ????<br><br>??
  • ????<input?type="submit"?value="提交"?><br/>??
  • </form>??
  • 上傳進度:<label?id="fileUploadProcess"></label>??
  • <iframe?name="iframeUpload"?src=""?width="350"?height="35"?frameborder=0??SCROLLING="no"?style="display:NONE"></iframe>?????
  • </body>??
  • </html>??
  • ?
    總結:

    雖然使用apache common upload組件實現了文件上傳,但是從上傳的效果來看,并不是一個很完美的解決方案。

    有如下缺點:

    1. 當有多個文件上傳時,無法知道單個文件的上傳進度,因為文件上傳消息中根本就沒有關于單個文件大小的信息

    文件上傳消息

    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    Content-Type: text/html;charset=UTF-8
    Transfer-Encoding: chunked
    Date: Tue, 22 Apr 2014 07:45:45 GMT

    POST /upload/uploadServlet HTTP/1.1
    Host: localhost:8080
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8080/upload/apacheUploadDemo.html
    Cookie: JSESSIONID=33498CE814284D67F957CA53D45F0174
    Connection: keep-alive

    Content-Length 2363
    Content-Type multipart/form-data; boundary=---------------------------189163093917262

    -----------------------------189163093917262
    Content-Disposition: form-data; name="name"?

    -----------------------------189163093917262
    Content-Disposition: form-data; name="file1"; filename="New Text Document.txt" Content-Type: text/plain
    文件數據

    -----------------------------189163093917262
    Content-Disposition: form-data; name="file2"; filename="New Text Document (2).txt" Content-Type: text/plain
    文件數據

    -----------------------------189163093917262--

    ??

    ?2. 瀏覽器必須將所有文件讀取完畢才開始上傳,并且是一次性提交所有的數據文件,在互聯網環境下,會http連接超時,大文件無法上傳成功。

    ?

    3. 服務端判斷是否超過大小限制,是通過計算接收數據的累積字節數和限制大小比較,這種情況下,如果限制大小是30M,那么在服務端已經讀取了30M完成后才會拋出異常,多余的消耗的服務器的內存和硬盤空間

    ?

    所以基于這些原因,頁面表單 + RFC1897規范 + http協議上傳 + 后臺apache common upload組件接收的這種解決方案,不適合解決WEB頁面一次多文件上傳,大文件上傳情況,比較適合一次單個小文件附件的情況,如:博客附件,登記照片上傳,預覽等情況。

    總結

    以上是生活随笔為你收集整理的WEB文件上传之apache common upload使用(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。