Java與WebUploader相結(jié)合實現(xiàn)文件上傳功能(實例代碼)
之前自己寫小項目的時候也碰到過文件上傳的問題,沒有找到很好的解決方案。雖然之前網(wǎng)找各種解決方案的時候也看到過WebUploader,但沒有進一步深究。這次稍微深入了解了些,這里也做個小結(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("進入后臺...");
// 1.創(chuàng)建DiskFileItemFactory對象,配置緩存用
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
// 2. 創(chuàng)建 ServletFileUpload對象
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
// 3. 設置文件名稱編碼
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. 獲取文件的實際內(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ā),預覽、壓縮,多途徑添加文件夾(文件多選,拖拽等),妙傳
頁面樣式使用
<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>
- 生成文件名列表、實時顯示上傳進度、顯示縮略圖
- 增加文件列表div,
<div id="fileList"></div> - 生成縮略圖和顯示上傳進度
// 生成縮略圖和上傳進度
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>無法預覽 </span>");
} else {
$("#" + file.id).find("img").attr("src", src);
}
});
}
);
// 監(jiān)控上傳進度
// percentage:代表上傳文件的百分比
uploader.on("uploadProgress", function(file, percentage) {
$("#" + file.id).find("span.percentage").text(Math.round(percentage * 100) + "%");
});
- 拖拽上傳、粘貼上傳
- 創(chuàng)建拖拽區(qū)域并設置樣式:
<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ū)域外的響應
開啟粘貼功能
var uploader = WebUploader.create(
{ swf:"${pageContext.request.contextPath }/js/Uploader.swf",
server:"${pageContext.request.contextPath }/FileUploadServlet",
pick:"#filePicker",
auto:true,
// 開啟拖拽
dnd:"#dndArea",
// 屏蔽拖拽區(qū)域外的響應
disableGlobalDnd:true,
//
}
);
- 文件的分塊上傳
前端根據(jù)需要發(fā)送的文件生成一個md5字符串發(fā)送給后臺,后臺創(chuàng)建以該md5字符串命名的文件夾。前端分塊發(fā)送文件并發(fā)送文件塊序號給后臺,后臺接收到文件后按序號名稱保存。前端發(fā)送完成后通知后臺合并文件。
- 前端配置,開啟是否分塊、分塊大小、線程個數(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",
// 分塊上傳設置
// 是否分塊
chunked:true,
// 每塊文件大?。J5M)
chunkSize:5*1024*1024,
// 開啟幾個并非線程(默認3個)
threads:3,
// 在上傳當前文件時,準備好下一個文件
prepareNextFile:true
}
);
- 前端監(jiān)聽分塊
可以分為三個時間點:
- before-send-file: 該方法在文件上傳前調(diào)用(只會在一個文件上傳前調(diào)用)。
可以在該方法中獲取文件的md5字符串作為后臺保存分塊文件的目錄名
- before-send: 該方法在每個分塊文件上傳前調(diào)用(每個分塊上傳前都會調(diào)用)。
可以在該方法中發(fā)送md5字符串到后臺,后臺判斷是否已經(jīng)存在分塊決定是否發(fā)送以達到斷點續(xù)傳的功能
- after-send-file: 該方法在所有文件上傳完成沒有錯誤之后調(diào)用(所有分塊上傳完成后調(diào)用)。
可以在該方法中通知后臺合并所有分塊
- 前端獲取文件md5字符串,發(fā)送每個分塊時發(fā)送到后臺,后臺接收如果不存在文件夾創(chuàng)建文件夾,保存分塊發(fā)送的文件
// 監(jiān)聽分塊上傳的時間點,斷點續(xù)傳
var fileMd5;
WebUploader.Uploader.register({
"before-send-file":"beforeSendFile",
"before-send":"beforeSend",
"after-send-file":"afterSendFile"
},{
beforeSendFile:function(file) {
// 創(chuàng)建一個deffered,用于通知是否完成操作
var deferred = WebUploader.Deferred();
// 計算文件的唯一標識,用于斷點續(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標簽
$("#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. 獲取文件的實際內(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進行合并文件
前端增加:
// 通知合并分塊
$.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("進入合并后臺...");
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();
}
// 關閉流
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);
}
}
- 斷點續(xù)傳
前端頁面發(fā)送前添加校驗,校驗是否已經(jīng)上傳分塊
beforeSend:function(block) {
var deferred = WebUploader.Deferred();
// 支持斷點續(xù)傳,發(fā)送到后臺判斷是否已經(jīng)上傳過
$.ajax(
{
type:"POST",
url:"${pageContext.request.contextPath}/UploadActionServlet?action=checkChunk",
data:{
// 文件唯一表示
fileMd5:fileMd5,
// 當前分塊下標
chunk:block.chunk,
// 當前分塊大小
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中添加校驗
else if ("checkChunk".equals(action)) {
// 校驗文件是否已經(jīng)上傳并返回結(jié)果給前端
// 文件唯一表示
String fileMd5 = request.getParameter("fileMd5");
// 當前分塊下標
String chunk = request.getParameter("chunk");
// 當前分塊大小
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é)合實現(xiàn)文件上傳功能(實例代碼),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- jquery組件WebUploader文件上傳用法詳解
- Java中使用WebUploader插件上傳大文件單文件和多文件的方法小結(jié)
- JavaScript中使用webuploader實現(xiàn)上傳視頻功能(demo)
- vue webuploader 文件上傳組件開發(fā)
- Android 開發(fā) 使用WebUploader解決安卓微信瀏覽器上傳圖片中遇到的bug
- 推薦三款不錯的圖片壓縮上傳插件(webuploader、localResizeIMG4、LUploader)
- 百度多文件異步上傳控件webuploader基本用法解析
- jQuery webuploader分片上傳大文件
- 基于WebUploader的文件上傳js插件
- WebUploader客戶端批量上傳圖片 后臺使用springMVC
相關文章
Java中SSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法
這篇文章主要介紹了 SSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-02-02
解決BigDecimal轉(zhuǎn)long丟失精度的問題
這篇文章主要介紹了解決BigDecimal轉(zhuǎn)long丟失精度的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
東方通TongWeb結(jié)合Spring-Boot使用的實現(xiàn)
本文主要介紹了東方通TongWeb結(jié)合Spring-Boot使用的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-07-07
百度翻譯API使用詳細教程(前端vue+后端springboot)
這篇文章主要給大家介紹了關于百度翻譯API使用的相關資料,百度翻譯API是百度面向開發(fā)者推出的免費翻譯服務開放接口,任何第三方應用或網(wǎng)站都可以通過使用百度翻譯API為用戶提供實時優(yōu)質(zhì)的多語言翻譯服務,需要的朋友可以參考下2024-02-02

