1、背景javascript
前段時間公司要求我作一個上傳和下載固件的頁面,以備硬件產品在線升級,如今我把這部分功能抽取出來做爲一個Demo Project給你們分享。css
2、源碼前端
前端java
js庫:jquery-3.2.1.min.js,jquery.form.js(異步表單提交),jsviews.min.js(模板渲染)jquery
jsviews科普:jsviews是實現MVVM的js庫,分爲JsRender(渲染),JsViews(數據視圖雙向綁定),JsObservable (數據監聽),有興趣的同窗能夠去官網瞭解,這裏只用到了渲染的功能。web
一、下載頁面 index.htmlajax
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ajaxSubmit上傳</title> <link rel="shortcut icon" href="images/favicon.ico"> <link rel="Bookmark" href="images/favicon.ico"> <link rel="stylesheet" href="css/index.css" /> <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script> <script type="text/javascript" src="js/jquery.form.js"></script> <script type="text/javascript" src="js/jsviews.min.js"></script> <script type="text/javascript" src="js/common.js"></script> </head> <body> <h1>上傳下載Demo</h1> <h2>一、上傳文件</h2> <form id="addForm"> <div> <span>選擇類型:</span> <select name="code" id="code"> <option value="0">普通開關</option> <option value="1">插座</option> </select> </div> <div> <span>選擇文件(小於5k):</span> <input type="file" id="file" name="file"> </div> <div> <button type="button" id="addConfirm" name="addConfirm">肯定</button> </div> </form> <h2>二、測試上傳結果</h2> <table id="tbBody"> <thead> <tr><td>類型</td><td>文件名</td><td>經過Servlet下載</td></tr> </thead> </table> </body> <script type="text/javascript" src="js/index.js"></script> <!-- jsviews模板 --> <script id="listTmpl" type="text/x-jsrender"> <tr> <td> {^{if code=='0'}}普通開關 {{else code=='1'}}插座 {{else}}數據錯誤{{/if}} </td> <td>{{:fileName}}</td> <td><a href="fileDownload?fileName={{:fileName}}">urlServlet</a></td> </tr> </script> </html>
二、公共js js/common.jsjson
//獲取連接參數 function getQueryString(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if(r!=null)return unescape(r[2]); return null; }
三、 js/index.js後端
//提交表單 function addSubmit(){ var options={ url: "fileUpload", type:'post', datatype:'json', success: function (data) { var result = JSON.parse(data); if(result.code == "0000"){ var pageBarTmpl = $.templates("#listTmpl"); var html = pageBarTmpl.render(result.content); $("#tbBody").append(html); }else{ alert(result.desc); } } } $("#addForm").ajaxSubmit(options); } //提交前檢查 function submitCheck(){ var code = $("#code").val(); if (!code) { alert("請選擇類型"); return false; } var file = $("#file").val(); if (!file) { alert("請選擇須要上傳的固件"); return false; } return true; } //按鈕觸發 $("#addConfirm").click(function(){ if(submitCheck()) addSubmit(); });
四、css/index.css
table th,table td{ border:1px solid black; } form div{ margin:5px; }
後端
使用到了commons-fileupload-1.3.1.jar,commons-io-2.4.jar以及gson-2.6.2.jar
一、返回結果類 RspResult.java
/** * 返回結果類 * @author zhang * */ public class RspResult{ private String code; //返回碼 private String desc; //返回描述 private Map<String,Object> content; //返回內容 public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public Map<String, Object> getContent() { return content; } public void setContent(Map<String, Object> content) { this.content = content; } }
二、自定義異常類 MyException.java
/** * 自定義異常 * @author zhang * */ public class MyException extends Exception{ private static final long serialVersionUID = 3075956744530570774L; private String code; //錯誤碼 private String desc; //描述 public MyException(String code, String desc) { super(); this.code = code; this.desc = desc; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
三、文件上傳Servlet FileUpload.java
/** * 文件上傳類 * 使用commons-fileupload工具包解析表單內容,捕獲自定義異常 * @author zhang * */ public class FileUpload extends HttpServlet{ private static final long serialVersionUID = -4700695646596658600L; private static final String SAVE_LOCATION = "/home/www/download/blog/ajaxUpload/"; //保存地址 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException { resp.setCharacterEncoding("UTF-8"); RspResult result = new RspResult(); result.setCode("0000"); result.setDesc("success"); try { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); upload.setFileSizeMax( 5*1024 ); //單個文件最大上傳大小爲5k upload.setSizeMax( 5*1024 ); //設置所有文件最大上傳總大小爲5k upload.setHeaderEncoding("utf-8"); //設置編碼 List<FileItem> fileItems = upload.parseRequest(req); Iterator<FileItem> iterator = fileItems.iterator(); Map<String, Object> rspConent = new HashMap<>(); DiskFileItem fileItem = null; //循環讀取表單數據 while (iterator.hasNext()) { FileItem item = iterator.next(); if (!item.isFormField()) { //是否爲文件類型,由於只有一個文件,因此單個引用就行 fileItem = (DiskFileItem) item; }else { rspConent.put(item.getFieldName(), item.getString()); } } if(fileItem == null) throw new MyException("0001","無選擇文件"); String fileName = fileItem.getName(); fileItem.write(new File(SAVE_LOCATION + fileName)); rspConent.put("fileName", fileName); result.setContent(rspConent); } catch (FileUploadException e ) { result.setCode("0001"); result.setDesc("文件上傳大小爲5k"); e.printStackTrace(); } catch (MyException e ) { //取得自定義異常結果 result.setCode(e.getCode()); result.setDesc(e.getDesc()); } catch (Exception e) { result.setCode("0001"); result.setDesc("未知錯誤"); e.printStackTrace(); }finally { PrintWriter out = null; try { out = resp.getWriter(); } catch (IOException e) { e.printStackTrace(); } out.write(new Gson().toJson(result)); } } }
四、文件下載Servlet FileDownload.java
/** * 文件下載類,讀取文件,以字節流形式寫到response * @author admin * */ public class FileDownload extends HttpServlet { private static final long serialVersionUID = -9135576688701595777L; private final String SAVE_LOCATION = "/home/www/download/blog/ajaxUpload/"; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException { InputStream in = null; try { String fileName = req.getParameter("fileName"); in = new FileInputStream(SAVE_LOCATION+fileName); // 設置輸出格式 resp.setCharacterEncoding("utf-8"); resp.addHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\""); // 讀取數據 byte[] b = new byte[100]; int len = 0; while ((len = in.read(b)) > 0) resp.getOutputStream().write(b, 0, len); } catch (UnsupportedEncodingException e2) { e2.printStackTrace(); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(in != null) in.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } }
配置
一、項目配置 web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>upload-download-demo</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>fileUpload</servlet-name> <servlet-class>com.yuejia.servlet.FileUpload</servlet-class> </servlet> <servlet-mapping> <servlet-name>fileUpload</servlet-name> <url-pattern>/fileUpload</url-pattern> </servlet-mapping> <servlet> <servlet-name>fileDownload</servlet-name> <servlet-class>com.yuejia.servlet.FileDownload</servlet-class> </servlet> <servlet-mapping> <servlet-name>fileDownload</servlet-name> <url-pattern>/fileDownload</url-pattern> </servlet-mapping> </web-app>
二、tomcat配置url支持utf-8 server.xml
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
3、總結
本Demo適合一次性上傳小文件,多數狀況下須要先上傳文件再進行表單提交,視需求而定。
在保存文件建議在文件名後面加上時間戳,保證同名文件不會被覆蓋。
以上!