要說邏輯其實也不難,新建一個form表單,表單有action處理頁面,action頁面就是處理上傳的頁面,這個dropzone插件的任務就是幫你對上傳的文件進行列隊上傳,就像管理員:你們這群孩子,領獎狀就要排好隊,一次上n個(默認是2個,可配置)來領獎,后面的同學排好隊,等待領獎。並且監聽每一個文件的上傳狀態。接下來上代碼:
index.jsp(注意,此form需要添加class="dropzone",因為這個是dropzone.css給dropzone類定義的樣式)
官方文檔(英文版):https://www.dropzonejs.com/#event-sending
官方文檔(中文版):http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/#installation
<%@ 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>dropzone上傳插件測試</title>
<!-- jquery -->
<script type="text/javascript" src="${pageContext.request.contextPath }/static/js/jquery-3.3.1.min.js"></script>
<!-- 注意:引入dropzone的js和css文件最好放在同一個目錄,不然的話,會出現各種錯誤 -->
<script type="text/javascript" src="${pageContext.request.contextPath }/static/dropzone/dropzone.js"></script>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/dropzone/dropzone.css" >
<style type="text/css">
#uploadForm {
min-height: 200px;
width: 800px;
margin-right: -810px;
margin-bottom: 30px;
display: inline-block;
background-color:white;
}
#uploadForm #uploadBtn {
position: absolute;
top: 2px;
right: -294px;
font-family: "方正舒體";
font-size: 40px;
width: 276px;
height: 80px;
cursor: pointer;
}
</style>
<script type="text/javascript">
/* Dropzone上傳插件配置 */
var IsServerError = false;//服務器獲取配置出錯
var fileList = new Array();
var fileList_Uploading = new Array();
var uploaded_filePaths = new Array();//已上傳的文件在服務器的路徑集合;用於遇到異常時刪除已上傳的文件。(相當於回滾)
var arr_file = new Array();
var arr_xhr = new Array();
Dropzone.options.uploadForm = { //此處的"uploadForm" 是dropzone的HTML元素ID的駝峰命名,比如<form id="my-form"></form>,那么此處應該寫:Dropzone.options.myForm
paramName: "MyFile", //上傳字段名 filedName
maxFiles: 100, //最大上傳數量
maxFilesize:1000, // MB 單個文件大小上限
filesizeBase:1000,
acceptedFiles: ".doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar,.7z,.txt,image/*,application/pdf,.psd",
addRemoveLinks: true,
clickable: true,
autoProcessQueue: true, // true:自動上傳,一次性上傳parallelUploads個文件,上傳成功后后面排隊的其他隊伍也會繼續排隊上傳。false:關閉自動上傳, 手動調度 ,但每次需要點擊“上傳”按鈕才會觸發上傳,排隊的其他文件不會自動上傳。
parallelUploads: 2, //最大並行處理量(一次同時上傳的個數,不設置的話,默認:2個)
/* 插件消息翻譯 */
/* dictDefaultMessage: '<i class="fa fa-cloud-upload"></i>拖拉文件上傳<br />或 <i class="fa fa-thumbs-down"></i>點此上傳', */
dictInvalidFileType: '僅支持以下格式文件:.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar,.7z,.txt,image/*,application/pdf,.psd',
dictFileTooBig: '文件超出最大10M約束',
dictMaxFilesExceeded: '超出最大上傳數量',
dictCancelUpload: '取消上傳',
dictRemoveFile: '刪除',
dictCancelUploadConfirmation: '確認取消上傳',
dictResponseError:"文件上傳失敗!",
dictDefaultMessage:"<span class='bigger-150 bolder'><i class='icon-caret-right red'></i>拖動文件</span>上傳\ <span class='smaller-80 gre'>(或者點擊上傳)</span> <br /> \ <i class='upload-icon icon-cloud-upload blue icon-3x'></i>",
/* 上傳縮略圖預覽模板 */
previewTemplate: ' <div id="viewer" class="dz-preview dz-file-preview"> <div class="dz-details" onClick="viewFile(this)" name=""> <div style="display:none;" class="fileId"></div> <div class="dz-filename"><span data-dz-name></span></div> <div class="dz-size" data-dz-size></div> <img data-dz-thumbnail /> </div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-success-mark"><span>?</span></div> <div class="dz-error-mark"><span>?</span></div> <div class="dz-error-message"><span data-dz-errormessage>""</span></div> </div> ',
/*accept: function(file, done) {
fileList_Accepted.push(file)
done();
}, */
init: function(){
/* var self = this;
// 非自動上傳。點擊上傳按鈕開始ajax上傳
this.element.querySelector("button#uploadBtn").addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
self.processQueue();
}); */
/*var accept = this.getAcceptedFiles();//所有接受的文件(合法)
var reject = this.getRejectedFiles();//所有拒絕的文件(非法)
var uploading = this.getQueuedFiles();//所有上傳中的文件
var queued = this.getRejectedFiles(); //所有排隊中的文件
*/
var this_ = this;
fileList = this.getAcceptedFiles();//所有接受的文件(合法)
this.on("addedfile", function(file) { //新添加的文件,每添加一個新文件都會觸發一次該函數,可以使用alert測試一下
//alert("addedfile:"+file.name)
//fileList.push(file);
})
this.on("canceled", function(file,response) { //當取消文件上傳式調用
//單個文件點擊“取消上傳”並確認后執行該函數,將該文件從上傳列隊中移除。
for(var i in arr_file){
if(arr_file[i].name.trim()==file.name.trim()){
var xhr = arr_xhr[i];
xhr.abort();
}
}
})
this.on("sending", function(file,xhr,formData) { //文件上傳前調用
arr_file.push(file);
arr_xhr.push(xhr);
})
this.on("uploadprogress", function(file,progress,bytesSent) { //文件上傳監聽器(file:文件、progress:上傳進度n%、bytesSent:)
})
this.on("complete", function(file,response) { //當上傳完成,成功或者出現錯誤時調用.
//alert("complete:"+response)
})
this.on("success", function(file,response) { //文件已經成功上傳,獲得服務器返回信息作為第二個參數
//每個文件上傳成功后有以下處理
//1.該文件會自動將UI拼接到上傳區域,我們需要將文件的服務器路徑隱藏到該UI中。為移除等操作提供便利。
IsServerError = JSON.parse(JSON.parse(response).error)
var File_PhysicalPath = "";
var list = JSON.parse(JSON.parse(response).list_client)
for(var k in list){
var file0 = list[k];
//alert(file0.fileName.trim()+":"+file.name+"\n"+file0.fileSize+":"+file.size)
if(file0.fileName.trim()==file.name&&file0.fileSize==file.size){
File_PhysicalPath = file0.physical_path;
}
}
$(".dz-filename span").each(function(){
if($(this).text().trim()==file.name.trim()){
$(this).parent().parent().find(".fileId").text(File_PhysicalPath);
uploaded_filePaths.push(File_PhysicalPath);
}
})
});
this.on("queuecomplete", function(file,response) { //當上傳隊列中的所有文件上傳完成時調用.
//alert("任務完成!")
if(IsServerError){
alert("服務器獲取文件夾配置失敗!即將回滾上傳操作");//若提示該警告,請查看com.nbc.demok.io.Upload.multi_upload()方法中的PropertiesUtils.getProperty("")獲取配置是否為空。為空的話,請及時在配置文件中添加該配置
//1.后台:遇到服務器異常,刪除已上傳的服務器上的文件
var filePaths = "";
for(var i in uploaded_filePaths){
var path = uploaded_filePaths[i];
if(path!=""){
filePaths = (filePaths=="")?path:(filePaths+"¤¤¤¤¤"+path);
}
}
if(filePaths.trim()!=""){
removeFiles_From_Server(filePaths);//服務器:移除所有未遇到錯誤之前的剛剛上傳了的文件
}
//2.前端:移除所有顯示的附件
this.removeAllFiles(true);
}
});
this.on("removedfile", function(file) { //刪除單一文件
//alert("removedfile:"+file.name+"\npath:"+$(file.previewElement).find(".fileId").text())
//文件在服務器上的路徑
var filePath = $(file.previewElement).find(".fileId").text().trim();
//刪除文件操作有以下步驟:
//1.使用ajax刪除在服務器上的該文件
if(filePath!=""){
removeFiles_From_Server(filePath);
}
//2.刪除文件在前端的顯示
this.removeFile(file);
});
this.on("error", function(file, errorMessage){ //不接受該文件(非定義的可接受類型)或上傳失敗
//alert("error:"+file.name+" "+errorMessage+"\nIsServerError:"+IsServerError)
//this.removeFile(file);
});
}
};
function removeFiles_From_Server(filePaths){
var path = $("#basePath").val();
if(path==undefined){
alert("獲取工程根目錄出錯");//請查看頁面是否有id="basePath"的輸入框,並且該輸入框存放項目根目錄
return;
}
$.ajax({
type:"POST",
timeout: 60000,
dataType:"json",
url:path+"/backend/upload.jsp?method=remove", //后台url請求,處理傳遞的參數
async: false,
data:{
filePaths:escape(escape(filePaths))
},
beforeSend: function (xhr) {
$("#loading_").css("display","block"); // 數據加載成功之前,使用loading組件(使用加載中的圖片,顯示圖片gif即可)
},
success:function(data){
//ajax請求成功執行該函數
$("#loading_").css("display","none"); //關閉加載中圖片
//alert("刪除成功,數量:"+data.count+"個")
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
$("#loading_").css("display","none") //
if(textStatus=="timeout"){
alert(" 請求超時,可能是網絡較慢,請重新加載")
}else{
alert("XMLHttpRequest.status:"+XMLHttpRequest.status+"\n"+"XMLHttpRequest.readyState:"+XMLHttpRequest.readyState+"\n"
+"textStatus:"+textStatus);
}
}
});
}
function viewFile(obj){
var filePath = $(obj).find(".fileId").text();
if(filePath.trim().length>0){
p = filePath.split(".");
var suffix = "."+p[p.length-1]; //后綴為 [.doc .docx .xls .xlsx .ppt .pptx]可以轉pdf在線瀏覽
//alert(suffix);
var IsOffice = false;
var arr = new Array(".doc",".docx",".xls",".xlsx",".ppt",".pptx")
for(var i in arr){
if(suffix==arr[i].trim()){
IsOffice = true;
}
}
if(IsOffice){
Open_Office_File(filePath)
}else{
Open_Not_Office_File(filePath);
}
}
}
function Open_Office_File(path){
alert("查看文件處理:"+path)
}
function Open_Office_File(path){
alert("查看文件處理:"+path)
}
</script>
</head>
<body>
<!-- 工程根目錄 -->
<input type="hidden" id="basePath" value="<%=request.getContextPath()%>"/>
<br>
<form id="uploadForm" action="backend/upload.jsp" class="dropzone">
<!-- <button id="uploadBtn" class="btn btn-success"> 確 認 上 傳 </button> -->
</form>
</body>
</html>
上面的代碼是圖一效果圖。
然后激活dropzone的腳本也有了,配置也有注釋了,我就挑幾個再講講吧
addRemoveLinks:true//每個文件添加“刪除”鏈接
acceptedFiles:定義的是可接受文件類型,也就是在選擇文件時幫你篩選以上類型的文件出來給你選。
parallelUploads:最大並行處理量,也就是上面提到的,一次上來n個孩子上台領獎,這個n是多少,就是在此處配置。
autoProcessQueue:默認是true,為true代表文件拖放到上傳域或選擇文件之后馬上幫你上傳,相當於自動上傳。如果設置為false的話,那選擇文件后不會進行上傳,只是單純的把文件列出來,當點擊“上傳”按鈕才會觸發上傳,這個按鈕需要綁定click事件來觸發上傳,也就是我上面的init函數注釋掉的,那個就是用來進行手動觸發上傳的。但手動觸發上傳存在一個大大的問題,就是點擊一次幫你上傳parallelUploads個文件,后面排隊的文件不會繼續上傳,需要再點擊一次上傳,那排隊中的下兩個才會觸發上傳,因此,要么你設置該參數為true(自動上傳),要么你設置為false(手動上傳)並且將parallelUploads設置得大一點(如:100)。這樣,上傳者才會好受一點。個人覺得還是用自動上傳最好。
previewTemplate:每一個文件的html模板,如上圖圖二,不管上傳成功 / 上傳中 / 等待上傳的文件都使用這個html模板進行拼接。注意:是以這個html作為模板進行拼接,顯示。
事件:
addedfile:每拖放/選擇一個文件進來都會執行一次該函數
canceled:取消上傳該文件。取消后會自動調用removedfile事件
uploadprogress:文件上傳中的處理,dropzone原本已經做好了進度條控制,你要自定義進度條的話,在這里進行自定義配置
success:每一個文件上傳成功都會觸發該函數。
queuecomplete:當所有文件處理完成執行該函數
removedfile:移除該文件(注意:dropzone僅將前端的UI刪除,並不會真正刪除你服務器上面的文件,因此,需要在該函數添加一個ajax事件進行刪除服務器上的該文件。刪除文件,那就需要文件所在路徑,那,我怎么知道這個文件的路徑?哈哈,所以我在html模板添加了一個div用來存放這個服務器文件的路徑,我說了,每上傳成功一個文件就會觸發一次success事件,我們就在這個事件里面將上傳成功的文件路徑放到html模板中,然后系統會自動拼接這個html模板到上傳域中,你說,我是不是很聰明。哈哈)
error:文件不在可接受文件類型范圍內 / 上傳失敗 時觸發該函數。
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.gson.Gson;
import upload.model.UploadResult;
public class Upload {
public static String basePath = "D:/WebSite/KMS";
public static String baseFoder = "Test";
/*
* @version 1.0
* @author Demonor
* @Class IsUsing = true
* */
public static void multi_upload(String UID,HttpSession session,HttpServletRequest request,HttpServletResponse response) throws IOException, JSONException{
boolean error = false;
String physical_path = "";
String server_path = "";
UploadResult result = new UploadResult();
List<UploadResult> list_client = new ArrayList<UploadResult>();
List<UploadResult> list_server = new ArrayList<UploadResult>();
Gson gson = new Gson();
JSONObject json = new JSONObject();
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
SimpleDateFormat fmt = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS");
String date = fmt.format(System.currentTimeMillis());
error = (baseFoder.equals(""))?true:false;
String upload_foder = basePath+"/"+baseFoder;
error = (upload_foder.equals(""))?true:false;
System.out.println("error:"+error);
if(!error) {
upload.setHeaderEncoding("UTF-8");
try{
List items = upload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString("utf-8");
} else {
String fieldName = item.getFieldName();
String OriginalName = item.getName().substring(item.getName().lastIndexOf("\\")+1);
String fileName = OriginalName.substring(0, OriginalName.lastIndexOf("."))+"¤※◎"+String.valueOf(UID)+"_"+date+"¤※◎"+item.getName().substring(item.getName().lastIndexOf("."),item.getName().length());;
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
File f = new File(upload_foder);
if(!f.exists()) {
f.mkdirs();
}
server_path = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/temp/"+fileName;
physical_path = upload_foder+"/"+fileName;
File uploadedFile = new File(physical_path);
System.out.println("physical_path:"+physical_path);
//System.out.println("fileName:"+fileName);
//System.out.println(uploadedFile.length()+"============");
item.write(uploadedFile);
list_server.add(new UploadResult(fileName,uploadedFile.length(),physical_path,""));
list_client.add(new UploadResult(OriginalName,uploadedFile.length(),physical_path,""));
}
} /* while */
}catch(Exception e){
e.printStackTrace();
}
}
response.setContentType("text/text;charset=utf-8");
PrintWriter out = response.getWriter();
json.put("error", error);
json.put("list_server", gson.toJson(list_server));
json.put("list_client", gson.toJson(list_client));
out.print(json.toString()); //
out.flush();
out.close();
}
public static int removeFile(String[] paths,HttpSession session) {
int k = 0;
for(String filePath : paths) {
boolean b = false;
filePath = ScriptDecoder.unescape(ScriptDecoder.unescape(filePath));
File file = new File(filePath);
if (!file.exists()) {
System.out.println("系統找不到指定的路徑:" + filePath);
}else{
b = file.delete();
k ++;
}
}
return k;
}
}
model:
import java.io.Serializable;
public class UploadResult implements Serializable{
/**
*
*/
private static final long serialVersionUID = 7434128027715196787L;
private String fileName; //文件名稱
private long fileSize; //文件大小
private String physical_path;//文件上傳到服務器的物理路徑
private String server_path; //文件上傳到服務器的服務器路徑,可訪問的http://xxx.com/xxx.png
public UploadResult() {}
public UploadResult(String fileName,long fileSize,String physical_path,String server_path) {
this.fileName = fileName;
this.fileSize = fileSize;
this.physical_path = physical_path;
this.server_path = server_path;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public String getPhysical_path() {
return physical_path;
}
public void setPhysical_path(String physical_path) {
this.physical_path = physical_path;
}
public String getServer_path() {
return server_path;
}
public void setServer_path(String server_path) {
this.server_path = server_path;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
————————————————
版權聲明:本文為CSDN博主「Demonor_」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/A13432421434/article/details/87860661