Java與WebUploader相結(jié)合實(shí)現(xiàn)文件上傳功能(實(shí)例代碼)
之前自己寫小項(xiàng)目的時(shí)候也碰到過文件上傳的問題,沒有找到很好的解決方案。雖然之前網(wǎng)找各種解決方案的時(shí)候也看到過WebUploader,但沒有進(jìn)一步深究。這次稍微深入了解了些,這里也做個(gè)小結(jié)。
簡單的文件和普通數(shù)據(jù)上傳并保存
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>Insert title here</title> </head> <body> <form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data"> 文件:<input type="file" value="請選擇文件" name="file" /> <br/> 信息:<input type="text" name="info" /> <br/> <input type="submit" value="提交" /> </form> </body> </html>
servlet:
package com.yihengliu.web.action; import java.io.File; import java.io.IOException; import java.io.InputStream; 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.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; /** * Servlet user to accept file upload */ public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private String serverPath = "e:/"; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("Served at: ").append(request.getContextPath()); System.out.println("進(jìn)入后臺..."); // 1.創(chuàng)建DiskFileItemFactory對象,配置緩存用 DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); // 2. 創(chuàng)建 ServletFileUpload對象 ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory); // 3. 設(shè)置文件名稱編碼 servletFileUpload.setHeaderEncoding("utf-8"); // 4. 開始解析文件 try { List<FileItem> items = servletFileUpload.parseRequest(request); for (FileItem fileItem : items) { if (fileItem.isFormField()) { // >> 普通數(shù)據(jù) String info = fileItem.getString("utf-8"); System.out.println("info:" + info); } else { // >> 文件 // 1. 獲取文件名稱 String name = fileItem.getName(); // 2. 獲取文件的實(shí)際內(nèi)容 InputStream is = fileItem.getInputStream(); // 3. 保存文件 FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name)); } } } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
使用WebUploader組件上傳
分片、并發(fā),預(yù)覽、壓縮,多途徑添加文件夾(文件多選,拖拽等),妙傳
頁面樣式使用
<html> <title>使用webuploader上傳</title> <!-- 1.引入文件 --> <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/js/webuploader.css" rel="external nofollow" > <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-2.1.4.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath }/js/webuploader.js"></script> </head> <body> <!-- 2.創(chuàng)建頁面元素 --> <div id="upload"> <div id="filePicker">文件上傳</div> </div> <!-- 3.添加js代碼 --> <script type="text/javascript"> var uploader = WebUploader.create( { swf:"${pageContext.request.contextPath }/js/Uploader.swf", server:"${pageContext.request.contextPath }/FileUploadServlet", pick:"#filePicker", auto:true } ); </script> </body> </html>
- 生成文件名列表、實(shí)時(shí)顯示上傳進(jìn)度、顯示縮略圖
- 增加文件列表div,
<div id="fileList"></div>
- 生成縮略圖和顯示上傳進(jìn)度
// 生成縮略圖和上傳進(jìn)度 uploader.on("fileQueued", function(file) { // 把文件信息追加到fileList的div中 $("#fileList").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='percentage'><span></div></div>") // 制作縮略圖 // error:不是圖片,則有error // src:代表生成縮略圖的地址 uploader.makeThumb(file, function(error, src) { if (error) { $("#" + file.id).find("img").replaceWith("<span>無法預(yù)覽 </span>"); } else { $("#" + file.id).find("img").attr("src", src); } }); } ); // 監(jiān)控上傳進(jìn)度 // percentage:代表上傳文件的百分比 uploader.on("uploadProgress", function(file, percentage) { $("#" + file.id).find("span.percentage").text(Math.round(percentage * 100) + "%"); });
- 拖拽上傳、粘貼上傳
- 創(chuàng)建拖拽區(qū)域并設(shè)置樣式:
<style type="text/css"> #dndArea { width: 200px; height: 100px; border-color: red; border-style: dashed; } </style> <!-- 創(chuàng)建用于拖拽的區(qū)域 --> <div id="dndArea"></div>
- 基本配置中增加dnd區(qū)域配置(開啟拖拽)
屏蔽拖拽區(qū)域外的響應(yīng)
開啟粘貼功能
var uploader = WebUploader.create( { swf:"${pageContext.request.contextPath }/js/Uploader.swf", server:"${pageContext.request.contextPath }/FileUploadServlet", pick:"#filePicker", auto:true, // 開啟拖拽 dnd:"#dndArea", // 屏蔽拖拽區(qū)域外的響應(yīng) disableGlobalDnd:true, // } );
- 文件的分塊上傳
前端根據(jù)需要發(fā)送的文件生成一個(gè)md5字符串發(fā)送給后臺,后臺創(chuàng)建以該md5字符串命名的文件夾。前端分塊發(fā)送文件并發(fā)送文件塊序號給后臺,后臺接收到文件后按序號名稱保存。前端發(fā)送完成后通知后臺合并文件。
- 前端配置,開啟是否分塊、分塊大小、線程個(gè)數(shù)等
// 上傳基本配置 var uploader = WebUploader.create( { swf:"${pageContext.request.contextPath }/js/Uploader.swf", server:"${pageContext.request.contextPath }/FileUploadServlet", pick:"#filePicker", auto:true, dnd:"#dndArea", disableGlobalDnd:true, paste:"#uploader", // 分塊上傳設(shè)置 // 是否分塊 chunked:true, // 每塊文件大?。J(rèn)5M) chunkSize:5*1024*1024, // 開啟幾個(gè)并非線程(默認(rèn)3個(gè)) threads:3, // 在上傳當(dāng)前文件時(shí),準(zhǔn)備好下一個(gè)文件 prepareNextFile:true } );
- 前端監(jiān)聽分塊
可以分為三個(gè)時(shí)間點(diǎn):
- before-send-file: 該方法在文件上傳前調(diào)用(只會在一個(gè)文件上傳前調(diào)用)。
可以在該方法中獲取文件的md5字符串作為后臺保存分塊文件的目錄名
- before-send: 該方法在每個(gè)分塊文件上傳前調(diào)用(每個(gè)分塊上傳前都會調(diào)用)。
可以在該方法中發(fā)送md5字符串到后臺,后臺判斷是否已經(jīng)存在分塊決定是否發(fā)送以達(dá)到斷點(diǎn)續(xù)傳的功能
- after-send-file: 該方法在所有文件上傳完成沒有錯(cuò)誤之后調(diào)用(所有分塊上傳完成后調(diào)用)。
可以在該方法中通知后臺合并所有分塊
- 前端獲取文件md5字符串,發(fā)送每個(gè)分塊時(shí)發(fā)送到后臺,后臺接收如果不存在文件夾創(chuàng)建文件夾,保存分塊發(fā)送的文件
// 監(jiān)聽分塊上傳的時(shí)間點(diǎn),斷點(diǎn)續(xù)傳 var fileMd5; WebUploader.Uploader.register({ "before-send-file":"beforeSendFile", "before-send":"beforeSend", "after-send-file":"afterSendFile" },{ beforeSendFile:function(file) { // 創(chuàng)建一個(gè)deffered,用于通知是否完成操作 var deferred = WebUploader.Deferred(); // 計(jì)算文件的唯一標(biāo)識,用于斷點(diǎn)續(xù)傳和妙傳 (new WebUploader.Uploader()).md5File(file, 0, 5*1024*1024) .progress(function(percentage){ $("#"+file.id).find("span.state").text("正在獲取文件信息..."); }) .then(function(val) { fileMd5 = val; $("#" + file.id).find("span.state").text("成功獲取文件信息"); // 放行 deferred.resolve(); }); // 通知完成操作 return deferred.promise(); }, beforeSend:function() { var deferred = WebUploader.Deferred(); // 發(fā)送文件md5字符串到后臺 this.owner.options.formData.fileMd5 = fileMd5; deferred.resolve(); return deferred.promise(); }, afterSendFile:function() { } } );
添加state標(biāo)簽
$("#fileList").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='state'></span></div><div><span class='percentage'></span></div></div>");
保存文件
// 4. 開始解析文件 // 文件md5獲取的字符串 String fileMd5 = null; // 文件的索引 String chunk = null; try { List<FileItem> items = servletFileUpload.parseRequest(request); for (FileItem fileItem : items) { if (fileItem.isFormField()) { // >> 普通數(shù)據(jù) String fieldName = fileItem.getFieldName(); if ("info".equals(fieldName)) { String info = fileItem.getString("utf-8"); System.out.println("info:" + info); } if ("fileMd5".equals(fieldName)) { fileMd5 = fileItem.getString("utf-8"); System.out.println("fileMd5:" + fileMd5); } if ("chunk".equals(fieldName)) { chunk = fileItem.getString("utf-8"); System.out.println("chunk:" + chunk); } } else { // >> 文件 /*// 1. 獲取文件名稱 String name = fileItem.getName(); // 2. 獲取文件的實(shí)際內(nèi)容 InputStream is = fileItem.getInputStream(); // 3. 保存文件 FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));*/ // 如果文件夾沒有創(chuàng)建文件夾 File file = new File(serverPath + "/" + fileMd5); if (!file.exists()) { file.mkdirs(); } // 保存文件 File chunkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk); FileUtils.copyInputStreamToFile(fileItem.getInputStream(), chunkFile); } }
- 前端通知action進(jìn)行合并文件
前端增加:
// 通知合并分塊 $.ajax( { type:"POST", url:"${pageContext.request.contextPath}/UploadActionServlet?action=mergeChunks", data:{ fileMd5:fileMd5 }, success:function(response){ } } );
新增合并action:
package com.yihengliu.web.action; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 合并上傳文件 */ public class UploadActionServlet extends HttpServlet { private static final long serialVersionUID = 1L; private String serverPath = "e:/"; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("進(jìn)入合并后臺..."); String action = request.getParameter("action"); if ("mergeChunks".equals(action)) { // 獲得需要合并的目錄 String fileMd5 = request.getParameter("fileMd5"); // 讀取目錄所有文件 File f = new File(serverPath + "/" + fileMd5); File[] fileArray = f.listFiles(new FileFilter() { // 排除目錄,只要文件 @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { return false; } return true; } }); // 轉(zhuǎn)成集合,便于排序 List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray)); // 從小到大排序 Collections.sort(fileList, new Comparator<File>() { @Override public int compare(File o1, File o2) { if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) { return -1; } return 1; } }); // 新建保存文件 File outputFile = new File(serverPath + "/" + UUID.randomUUID().toString() + ".zip"); // 創(chuàng)建文件 outputFile.createNewFile(); // 輸出流 FileOutputStream fileOutputStream = new FileOutputStream(outputFile); FileChannel outChannel = fileOutputStream.getChannel(); // 合并 FileChannel inChannel; for (File file : fileList) { inChannel = new FileInputStream(file).getChannel(); inChannel.transferTo(0, inChannel.size(), outChannel); inChannel.close(); // 刪除分片 file.delete(); } // 關(guān)閉流 fileOutputStream.close(); outChannel.close(); // 清除文件加 File tempFile = new File(serverPath + "/" + fileMd5); if (tempFile.isDirectory() && tempFile.exists()) { tempFile.delete(); } System.out.println("合并文件成功"); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
- 斷點(diǎn)續(xù)傳
前端頁面發(fā)送前添加校驗(yàn),校驗(yàn)是否已經(jīng)上傳分塊
beforeSend:function(block) { var deferred = WebUploader.Deferred(); // 支持?jǐn)帱c(diǎn)續(xù)傳,發(fā)送到后臺判斷是否已經(jīng)上傳過 $.ajax( { type:"POST", url:"${pageContext.request.contextPath}/UploadActionServlet?action=checkChunk", data:{ // 文件唯一表示 fileMd5:fileMd5, // 當(dāng)前分塊下標(biāo) chunk:block.chunk, // 當(dāng)前分塊大小 chunkSize:block.end-block.start }, dataType:"json", success:function(response) { if(response.ifExist) { // 分塊存在,跳過該分塊 deferred.reject(); } else { // 分塊不存在或不完整,重新發(fā)送 deferred.resolve(); } } } ); // 發(fā)送文件md5字符串到后臺 this.owner.options.formData.fileMd5 = fileMd5; return deferred.promise(); }
- action中添加校驗(yàn)
else if ("checkChunk".equals(action)) { // 校驗(yàn)文件是否已經(jīng)上傳并返回結(jié)果給前端 // 文件唯一表示 String fileMd5 = request.getParameter("fileMd5"); // 當(dāng)前分塊下標(biāo) String chunk = request.getParameter("chunk"); // 當(dāng)前分塊大小 String chunkSize = request.getParameter("chunkSize"); // 找到分塊文件 File checkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk); // 檢查文件是否存在,且大小一致 response.setContentType("text/html;charset=utf-8"); if (checkFile.exists() && checkFile.length() == Integer.parseInt((chunkSize))) { response.getWriter().write("{\"ifExist\":1}"); } else { response.getWriter().write("{\"ifExist\":0}"); } }
以上所述是小編給大家介紹的Java與WebUploader相結(jié)合實(shí)現(xiàn)文件上傳功能(實(shí)例代碼),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- jquery組件WebUploader文件上傳用法詳解
- Java中使用WebUploader插件上傳大文件單文件和多文件的方法小結(jié)
- JavaScript中使用webuploader實(shí)現(xiàn)上傳視頻功能(demo)
- vue webuploader 文件上傳組件開發(fā)
- Android 開發(fā) 使用WebUploader解決安卓微信瀏覽器上傳圖片中遇到的bug
- 推薦三款不錯(cuò)的圖片壓縮上傳插件(webuploader、localResizeIMG4、LUploader)
- 百度多文件異步上傳控件webuploader基本用法解析
- jQuery webuploader分片上傳大文件
- 基于WebUploader的文件上傳js插件
- WebUploader客戶端批量上傳圖片 后臺使用springMVC
相關(guān)文章
Java中SSM+Shiro系統(tǒng)登錄驗(yàn)證碼的實(shí)現(xiàn)方法
這篇文章主要介紹了 SSM+Shiro系統(tǒng)登錄驗(yàn)證碼的實(shí)現(xiàn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02解決BigDecimal轉(zhuǎn)long丟失精度的問題
這篇文章主要介紹了解決BigDecimal轉(zhuǎn)long丟失精度的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12東方通TongWeb結(jié)合Spring-Boot使用的實(shí)現(xiàn)
本文主要介紹了東方通TongWeb結(jié)合Spring-Boot使用的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07百度翻譯API使用詳細(xì)教程(前端vue+后端springboot)
這篇文章主要給大家介紹了關(guān)于百度翻譯API使用的相關(guān)資料,百度翻譯API是百度面向開發(fā)者推出的免費(fèi)翻譯服務(wù)開放接口,任何第三方應(yīng)用或網(wǎng)站都可以通過使用百度翻譯API為用戶提供實(shí)時(shí)優(yōu)質(zhì)的多語言翻譯服務(wù),需要的朋友可以參考下2024-02-02