© 版權聲明:本文為博主原創文章,轉載請注明出處
說明:
1. 使用commons-fileupload.jar實現文件上傳及進度監聽
2. 使用bootstrap的進度條進行頁面顯示
3. 因為進度數據保存在session中,所以同一個瀏覽器同時只能發送一次上傳請求,多次發送進度會錯亂
實例:
1.項目結構
2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.file</groupId> <artifactId>process</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- Junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- Commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency> </dependencies> <build> <finalName>process</finalName> </build> </project>
3.index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Excel上傳</title> <link rel="stylesheet" type="text/css" href="bootstrap/bootstrap.min.css"> </head> <body> <div class="container" align="center"> <form action="uploadExcel" method="post" enctype="multipart/form-data"> <table class="table" style="width: 50%"> <tr id="msg" style="display: none;"> <th colspan="2" style="text-align: center;"> <font color="#00CD00">文件上傳成功,共用時${time }ms</font> </th> </tr> <tr> <th>上傳文件1:</th> <td><input type="file" name="file"/></td> </tr> <tr> <th>上傳文件2:</th> <td><input type="file" name="file"/></td> </tr> <tr> <th>上傳人:</th> <td><input type="text" name="user"/></td> </tr> <tr> <th> </th> <td> <button id="submit" type="submit" class="btn btn-default">上傳</button> </td> </tr> </table> </form> </div> <!-- 文件上傳模態框 --> <div id="progressModal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">文件上傳進度</h4> </div> <div class="modal-body"> <div id="progress" class="progress"> <div id="progress_rate" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" style="width: 0%"> <span id="percent">0%</span> </div> </div> </div> </div> </div> </div> <script type="text/javascript" src="bootstrap/jquery-3.2.0.min.js"></script> <script type="text/javascript" src="bootstrap/bootstrap.min.js"></script> <script type="text/javascript"> var process;// 定時對象 $(function() { var time = "${time}"; if (time != null && time != "") { $("#msg").css("display", "block"); } $("#submit").bind("click", function(){ process = setInterval("getProcess()", 100);// 每0.1s讀取一次進度 $("#progressModal").modal("show");// 打開模態框 }); }); // 讀取文件上傳進度並通過進度條展示 function getProcess() { $.ajax({ type: "get", url: "uploadExcel", success: function(data) { var rate = data * 100; rate = rate.toFixed(2); $("#progress_rate").css("width", rate + "%"); $("#percent").text(rate + "%"); if (rate >= 100) { clearInterval(process); $("#percent").text("文件上傳成功!"); } } }); } </script> </body> </html>
4.UploadProcess.java
package org.file.upload; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.math.BigDecimal; import java.util.Calendar; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; @WebServlet("/uploadExcel") public class UploadProcess extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("開始上傳文件..."); // 使用session保存進度數據 final HttpSession session = req.getSession(); long start_time = Calendar.getInstance().getTimeInMillis(); // 獲取上傳文件臨時保存路徑 String tempPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File file = new File(tempPath); if (!file.exists() && !file.isDirectory()) {// 目錄不存在或不是一個目錄 file.mkdirs(); } try { // 創建DiskFileItemFactory工廠類 DiskFileItemFactory factory = new DiskFileItemFactory(); // 創建一個文件上傳解析器 ServletFileUpload upload = new ServletFileUpload(factory); // 監聽文件上傳進度 upload.setProgressListener(new ProgressListener() { public void update(long pBytesRead, long pContentLength, int pItems) { session.setAttribute("fileSize", pContentLength); session.setAttribute("loadSize", pBytesRead); } }); // 解決上傳文件的中文亂碼 upload.setHeaderEncoding("UTF-8"); if (!ServletFileUpload.isMultipartContent(req)) {// 普通表單 return ; } else { // 利用文件上傳解析器解析數據並存放到list中 List<FileItem> list = upload.parseRequest(req); // 循環所有數據 for (FileItem item: list) { // 判斷數據來源 if (item.isFormField()) {//普通輸入框中的數據 String name = item.getFieldName();// 輸入框的name值 String value = item.getString("UTF-8"); // 輸入框的值 System.out.println(name + " : " + value); } else {//文件 // 獲取上傳文件的文件路徑(不同瀏覽器不同,有的是文件名,有的是全路徑) String fileName = item.getName(); if (fileName == null || "".equals(fileName.trim())) { continue; } // 獲取文件名 fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); // 獲取上傳文件的輸入流 InputStream is = item.getInputStream(); // 創建一個文件輸出流 FileOutputStream fos = new FileOutputStream(tempPath + "\\" + fileName); // 創建一個緩存區 byte[] buff = new byte[1024]; int len = 0; while ((len = is.read(buff)) > 0) {// 循環讀取數據 fos.write(buff, 0, len);// 使用文件輸出流將緩存區的數據寫入到指定的目錄中 } // 關閉輸出流 fos.close(); // 關閉輸入流 is.close(); // 刪除臨時文件 item.delete(); } } } long end_time = Calendar.getInstance().getTimeInMillis(); long lt = end_time - start_time; System.out.println("文件上傳成功,共用時" + (end_time - start_time) + "ms"); req.setAttribute("time", lt); req.getRequestDispatcher("index.jsp").forward(req, resp); } catch (Exception e) { e.printStackTrace(); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 獲取進度數據 HttpSession session = req.getSession(); Object obj1 = session.getAttribute("loadSize"); long loadSize = 0L; if (obj1 != null) { loadSize = Long.valueOf(obj1.toString()); } Object obj2 = session.getAttribute("fileSize"); long fileSize = 1L; if (obj2 != null) { fileSize = Long.valueOf(obj2.toString()); } // 計算上傳比例 double rate = loadSize * 1.0 / fileSize; BigDecimal bd = new BigDecimal(rate); rate = bd.setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue(); // 返回 resp.setContentType("text/html;charset=UTF-8"); PrintWriter pw = resp.getWriter(); pw.write(rate + ""); pw.flush(); pw.close(); } }
5.效果預覽