參考鏈接:
https://blog.csdn.net/hjf_1291030386/article/details/74784172
https://www.cnblogs.com/tengyunhao/p/7670293.html
https://www.cnblogs.com/2050/p/3913184.html
配置文件:
<!-- 文件上傳 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8" /> <property name="resolveLazily" value="true"/> <property name="maxUploadSize" value="100000000" /> </bean>
.jsp(引用plupload.full.min.js文件)
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String ctx = request.getContextPath(); request.setAttribute("ctx", ctx); %> <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>XXX</title> </head> <body> <div> <button id="btnUploadFile">選擇文件</button> <button id="" onclick="fnUploadFile2()">開始上傳</button> </div> </body> <%-- <script type="text/javascript" src="${ctx }/common/js/jquery.js"></script> --%> <jsp:include page="../base/footer.jsp" /> <script type="text/javascript">var uploader = new plupload.Uploader({ //創建實例的構造方法 runtimes: 'html5,flash,silverlight,html4', //上傳插件初始化選用那種方式的優先級順序 browse_button: 'btnUploadFile', // 上傳按鈕 url:'${ctx}/fileUpload/pluploadFile', //遠程上傳地址 flash_swf_url: 'plupload/Moxie.swf', //flash文件地址 silverlight_xap_url: 'plupload/Moxie.xap', //silverlight文件地址 max_retries: 3, //允許重試次數 max_file_size: '2000mb', //最大上傳文件大小(格式100b, 10kb, 10mb, 1gb) chunk_size: '10mb',//分塊大小 filters: { mime_types: [ //允許文件上傳類型 { title: "files", extensions: "jpg,png,gif,mp4,docx,doc,pdf" } ] }, multipart:true,//為true時將以multipart/form-data的形式來上傳文件,為false時則以二進制的格式來上傳文件 multipart_params: {}, //文件上傳附加參數 file_data_name: "upimg", //文件上傳的名稱 multi_selection: false, //true:ctrl多文件上傳, false 單文件上傳 init: { FilesAdded: function(up, files) { //文件上傳前 //一個文件被添加了 //uploader為當前實例對象,files數組,上傳隊列里的文件對象 alert("add"); }, UploadProgress: function(up, file) { //上傳中,顯示進度條 //從這里我們可以動態得到控制前端的進度條顯示 //file.percent為當前的進度 //file.loaded為已經上傳的大小 //file.size為文件的總大小 }, FileUploaded: function(up, file, info) { //文件上傳成功的時候觸發 alert("success"); }, Error: function(up, err) { //上傳出錯的時候觸發 console.log(err.message); alert("error"); } } }); uploader.init(); ///開始上傳。 function fnUploadFile2() { uploader.start(); } </script> </html>
可綁定各種事件,並在事件監聽函數中做你想做的事
uploader.init(); //上傳之前綁定事件中重新定義url,傳值文件id uploader.bind('BeforeUpload',function(uploader,files){ uploader.settings.url='${ctx}/organization/topic/pluploadFile?topicId=${topicId}&fileId='+files.id;//遠程上傳地址 });
.java
package lee.files.controller; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; @Controller @RequestMapping("/fileUpload") public class uploadController { private static final int BUFFER_SIZE = 100*1024; /** * plupload上傳文件 * @param name 文件名 * @param chunks 文件塊數 * @param chunk 當前塊 * @param request * @return * @throws IllegalStateException * @throws IOException * * @RequestParam String name, @RequestParam(required = false, defaultValue = "-1") int chunks, @RequestParam(required = false, defaultValue = "-1") int chunk, HttpServletRequest request,String topicId */ @ResponseBody @RequestMapping(value="/pluploadFile",method=RequestMethod.POST) public String pluploadFile(@RequestParam(value="uploadFile",required = false) MultipartFile uploadFile, HttpServletRequest request){ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); String uploadTime = simpleDateFormat.format(date); //初始化通用multipart解析器 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //判斷請求中是否有文件上傳 if (!multipartResolver.isMultipart(request)) { //請求為空,直接返回 return null; } try { Integer chunk = 0, chunks = 0; if(null != request.getParameter("chunk") && !request.getParameter("chunk").equals("")){ chunk = Integer.valueOf(request.getParameter("chunk")); } if(null != request.getParameter("chunks") && !request.getParameter("chunks").equals("")){ chunks = Integer.valueOf(request.getParameter("chunks")); } String fileName = request.getParameter("name"); //解析請求,將文件信息放到迭代器里 MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; Iterator<String> iter = multiRequest.getFileNames(); //取得上傳文件 uploadFile = multiRequest.getFile(iter.next()); String path = buildTopicFilePath1(request); File saveFilePath = new File(path); if (!saveFilePath.exists()) { saveFilePath.mkdirs(); } //目標文件 File saveFile = new File(path,fileName); /*//文件已存在刪除舊文件(上傳了同名的文件) if (chunk == 0 && saveFile.exists()) { saveFile.delete(); saveFile = new File(saveFilePath, fileName); }*/ //合成文件 appendFile(uploadFile.getInputStream(), saveFile); if (chunk.equals(chunks-1)) { System.out.println("上傳完成"); }else { System.out.println("還剩["+(chunks-1-chunk)+"]個塊文件"); } }catch (Exception e) { } return ""; } /** * 合成分塊文件 * @param in * @param saveFile */ private void appendFile(InputStream in, File saveFile) { OutputStream out = null; try { // plupload 配置了chunk的時候新上傳的文件append到文件末尾 if (saveFile.exists()) { out = new BufferedOutputStream(new FileOutputStream(saveFile, true), BUFFER_SIZE); } else { out = new BufferedOutputStream(new FileOutputStream(saveFile),BUFFER_SIZE); } in = new BufferedInputStream(in, BUFFER_SIZE); int len = 0; byte[] buffer = new byte[BUFFER_SIZE]; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } } catch (Exception e) { } finally { try { in.close(); out.flush(); out.close(); } catch (IOException e) { } } } private String buildTopicFilePath1(HttpServletRequest request) { String cp = request.getContextPath().replace("/", ""); String path = request.getSession().getServletContext().getRealPath("").replace("\\"+cp, ""); String path_head = path+"/uploadfiles"; StringBuilder sb = new StringBuilder(); sb.append(path_head); return sb.toString(); } }
plupload介紹
一、配置參數
實例化一個plupload對象時,也就是 new plupload.Uploader()
,需要傳入一個對象作為配置參數。后面內容中出現的plupload實例均是指new plupload.Uploader()
得到的實例對象
屬性 | 類型 | 默認值 | 描述 |
---|---|---|---|
browse_button | String / DOM | 觸發文件選擇對話框的DOM元素,當點擊該元素后便后彈出文件選擇對話框。該值可以是DOM元素對象本身,也可以是該DOM元素的id | |
url | String | 服務器端接收和處理上傳文件的腳本地址,可以是相對路徑(相對於當前調用Plupload的文檔),也可以是絕對路徑 | |
filters | Object | { } | 可以使用該參數來限制上傳文件的類型,大小等,該參數以對象的形式傳入,它包括三個屬性: mime_types:用來限定上傳文件的類型,為一個數組,該數組的每個元素又是一個對象,該對象有title和extensions兩個屬性,title為該過濾器的名稱,extensions為文件擴展名,有多個時用逗號隔開。該屬性默認為一個空數組,即不做限制。 max_file_size:用來限定上傳文件的大小,如果文件體積超過了該值,則不能被選取。值可以為一個數字,單位為b,也可以是一個字符串,由數字和單位組成,如'200kb' prevent_duplicates:是否允許選取重復的文件,為true時表示不允許,為false時表示允許,默認為false。如果兩個文件的文件名和大小都相同,則會被認為是重復的文件 filters完整的配置示例如下(當然也可以只配置其中的某一項): filters: { mime_types : [ //只允許上傳圖片和zip文件 { title : "Image files", extensions : "jpg,gif,png" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上傳400kb的文件 prevent_duplicates : true //不允許選取重復文件 } |
headers | Object | 設置上傳時的自定義頭信息,以鍵/值對的形式傳入,鍵代表頭信息屬性名,鍵代表屬性值。html4上傳方式不支持設置該屬性。 | |
multipart | Boolean | true | 為true 時將以multipart/form-data 的形式來上傳文件,為false時則以二進制的格式來上傳文件。html4上傳方式不支持以二進制格式來上傳文件,在flash上傳方式中,二進制上傳也有點問題。並且二進制格式上傳還需要在服務器端做特殊的處理。一般我們用multipart/form-data的形式來上傳文件就足夠了。 |
multipart_params | Object | 上傳時的附加參數,以鍵/值對的形式傳入,服務器端可是使用$_POST來獲取這些參數(以php為例)。比如: multipart_params: { one: '1', two: '2', three: { //值還可以是一個字面量對象 a: '4', b: '5' }, four: ['6', '7', '8'] //也可以是一個數組 } |
|
max_retries | Number | 0 | 當發生plupload.HTTP_ERROR 錯誤時的重試次數,為0時表示不重試 |
chunk_size | Number/String | 0 | 分片上傳文件時,每片文件被切割成的大小,為數字時單位為字節。也可以使用一個帶單位的字符串,如"200kb" 。當該值為0時表示不使用分片上傳功能 |
resize | Object | 可以使用該參數對將要上傳的圖片進行壓縮,該參數是一個對象,里面包括5個屬性: width:指定壓縮后圖片的寬度,如果沒有設置該屬性則默認為原始圖片的寬度 height:指定壓縮后圖片的高度,如果沒有設置該屬性則默認為原始圖片的高度 crop: quality:壓縮后圖片的質量,只對jpg格式的圖片有效,默認為90。 preserve_headers:壓縮后是否保留圖片的元數據, resize參數的配置示例如下: resize: { width: 100, height: 100, crop: true, quality: 60, preserve_headers: false } |
|
drop_element | DOM/String/Array | 指定了使用拖拽方式來選擇上傳文件時的拖拽區域,即可以把文件拖拽到這個區域的方式來選擇文件。該參數的值可以為一個DOM元素的id,也可是DOM元素本身,還可以是一個包括多個DOM元素的數組。如果不設置該參數則拖拽上傳功能不可用。目前只有html5上傳方式才支持拖拽上傳。 | |
multi_selection | Boolean | true | 是否可以在文件瀏覽對話框中選擇多個文件,true為可以,false為不可以。默認true,即可以選擇多個文件。需要注意的是,在某些不支持多選文件的環境中,默認值是false。比如在ios7的safari瀏覽器中,由於存在bug,造成不能多選文件。當然,在html4上傳方式中,也是無法多選文件的。 |
required_features | Mix | 可以使用該參數來設置你必須需要的一些功能特征,Plupload會根據你的設置來選擇合適的上傳方式。因為,不同的上傳方式,支持的功能是不同的,比如拖拽上傳只有html5上傳方式支持,圖片壓縮則只有html5,flash,silverlight上傳方式支持。該參數的值是一個混合類型,可以是一個以逗號分隔的字符串, | |
unique_names | Boolean | false | 當值為true時會為每個上傳的文件生成一個唯一的文件名,並作為額外的參數post到服務器端,參數明為name ,值為生成的文件名。 |
runtimes | String | html5,flash, silverlight, html4 |
用來指定上傳方式,指定多個上傳方式請使用逗號隔開。一般情況下,你不需要配置該參數,因為Plupload默認會根據你的其他的參數配置來選擇最合適的上傳方式。如果沒有特殊要求的話,Plupload會首先選擇html5上傳方式,如果瀏覽器不支持html5,則會使用flash或silverlight,如果前面兩者也都不支持,則會使用最傳統的html4上傳方式。如果你想指定使用某個上傳方式,或改變上傳方式的優先順序,則你可以配置該參數。 |
file_data_name | String | file | 指定文件上傳時文件域的名稱,默認為file ,例如在php中你可以使用$_FILES['file'] 來獲取上傳的文件信息 |
container | DOM/String | 用來指定Plupload所創建的html結構的父容器,默認為前面指定的browse_button 的父元素。該參數的值可以是一個元素的id,也可以是DOM元素本身。 |
|
flash_swf_url | String | js/Moxie.swf | flash上傳組件的url地址,如果是相對路徑,則相對的是調用Plupload的html文檔。當使用flash上傳方式會用到該參數。 |
silverlight_xap_url | String | js/Moxie.xap | silverlight上傳組件的url地址,如果是相對路徑,則相對的是調用Plupload的html文檔。當使用silverlight上傳方式會用到該參數。 |
二、各種事件說明
要了解plupload的運行狀況,靠的就是在這些事件了
Init |
---|
當Plupload初始化完成后觸發 監聽函數參數:(uploader)
|
PostInit |
當Init事件發生后觸發 監聽函數參數:(uploader)
|
OptionChanged |
當使用Plupload實例的setOption()方法改變當前配置參數后觸發 監聽函數參數:(uploader,option_name,new_value,old_value)
|
Refresh |
當調用plupload實例的refresh()方法后會觸發該事件,暫時不清楚還有什么其他動作會觸發該事件,但據我測試,把文件添加到上傳隊列后也會觸發該事件。 監聽函數參數:(uploader)
|
StateChanged |
當上傳隊列的狀態發生改變時觸發 監聽函數參數:(uploader)
|
UploadFile |
當上傳隊列中某一個文件開始上傳后觸發 監聽函數參數:(uploader,file)
|
BeforeUpload |
當隊列中的某一個文件正要開始上傳前觸發 監聽函數參數:(uploader,file)
|
QueueChanged |
當上傳隊列發生變化后觸發,即上傳隊列新增了文件或移除了文件。QueueChanged事件會比FilesAdded或FilesRemoved事件先觸發 監聽函數參數:(uploader)
|
UploadProgress |
會在文件上傳過程中不斷觸發,可以用此事件來顯示上傳進度 監聽函數參數:(uploader,file)
|
FilesRemoved |
當文件從上傳隊列移除后觸發 監聽函數參數:(uploader,files)
|
FileFiltered |
暫不清楚該事件的意義,但根據測試得出,該事件會在每一個文件被添加到上傳隊列前觸發 監聽函數參數:(uploader,file)
|
FilesAdded |
當文件添加到上傳隊列后觸發 監聽函數參數:(uploader,files)
|
FileUploaded |
當隊列中的某一個文件上傳完成后觸發 監聽函數參數:(uploader,file,responseObject)
response:服務器返回的文本 responseHeaders:服務器返回的頭信息 status:服務器返回的http狀態碼,比如200 |
ChunkUploaded |
當使用文件小片上傳功能時,每一個小片上傳完成后觸發 監聽函數參數:(uploader,file,responseObject)
offset:該文件小片在整體文件中的偏移量 response:服務器返回的文本 responseHeaders:服務器返回的頭信息 status:服務器返回的http狀態碼,比如200 total:該文件(指的是被切割成了許多文件小片的那個文件)的總大小,單位為字節 |
UploadComplete |
當上傳隊列中所有文件都上傳完成后觸發 監聽函數參數:(uploader,files)
|
Error |
當發生觸發時觸發 監聽函數參數:(uploader,errObject)
code:錯誤代碼,具體請參考plupload上定義的表示錯誤代碼的常量屬性 file:與該錯誤相關的文件對象 message:錯誤信息 |
Destroy |
當調用destroy方法時觸發 監聽函數參數:(uploader)
|
三、Plupload實例的屬性
屬性 | 描述 |
---|---|
id | Plupload實例的唯一標識id |
state | 當前的上傳狀態,可能的值為plupload.STARTED 或plupload.STOPPED ,該值由Plupload實例的stop() 或statr() 方法控制。默認為plupload.STOPPED |
runtime | 當前使用的上傳方式 |
files | 當前的上傳隊列,是一個由上傳隊列中的文件對象組成的數組 |
settings | 當前的配置參數對象 |
total | 表示總體進度信息的QueueProgress對象 |
四、Plupload實例的方法
方法 | 描述 |
---|---|
init() | 初始化Plupload實例 |
setOption(option, [value]) | 設置某個特定的配置參數,option為參數名稱,value為要設置的參數值。option也可以為一個由參數名和參數值鍵/值對組成的對象,這樣就可以一次設定多個參數,此時該方法的第二個參數value會被忽略。 |
getOption([option]) | 獲取當前的配置參數,參數option為需要獲取的配置參數名稱,如果沒有指定option,則會獲取所有的配置參數 |
refresh() | 刷新當前的plupload實例,暫時還不明白什么時候需要使用 |
start() | 開始上傳隊列中的文件 |
stop() | 停止隊列中的文件上傳 |
disableBrowse(disable) | 禁用或啟用plupload的文件瀏覽按鈕,參數disable 為true 時為禁用,為false 時為啟用。默認為true |
getFile(id) | 通過id來獲取文件對象 |
addFile(file, [fileName]) | 向上傳隊列中添加文件,如果成功添加了文件,會觸發FilesAdded 事件。參數file為要添加的文件,可以是一個原生的文件,或者一個plupload文件對象,或者一個input[type="file"] 元素,還可以是一個包括前面那幾種東西的數組;fileName為給該文件指定的名稱 |
removeFile(file) | 從上傳隊列中移除文件,參數file 為plupload文件對象或先前指定的文件名稱 |
splice(start, length) | 從上傳隊列中移除一部分文件,start 為開始移除文件在隊列中的索引,length 為要移除的文件的數量,該方法的返回值為被移除的文件。該方法會觸發FilesRemoved 和QueueChanged 事件 |
trigger(name, Multiple) | 觸發某個事件。name 為要觸發的事件名稱,Multiple 為傳給該事件監聽函數的參數,是一個對象 |
hasEventListener(name) | 用來判斷某個事件是否有監聽函數,name 為事件名稱 |
bind(name, func, scope) | 給某個事件綁定監聽函數,name 為事件名,func 為監聽函數,scope 為監聽函數的作用域,也就是監聽函數中this的指向 |
unbind(name, func) | 移除事件的監聽函數,name 為事件名稱,func 為要移除的監聽函數 |
unbindAll() | 移除所有事件的所有監聽函數 |
destroy() | 銷毀plupload實例 |
五、文件對象的屬性和方法
在很多事件監聽函數中,都會提供文件對象給你
屬性/方法 | 描述 |
---|---|
id | 文件id |
name | 文件名,例如"myfile.gif" |
type | 文件類型,例如"image/jpeg" |
size | 文件大小,單位為字節,當啟用了客戶端壓縮功能后,該值可能會改變 |
origSize | 文件的原始大小,單位為字節 |
loaded | 文件已上傳部分的大小,單位為字節 |
percent | 文件已上傳部分所占的百分比,如50就代表已上傳了50% |
status | 文件的狀態,可能為以下幾個值之一:plupload.QUEUED , plupload.UPLOADING , plupload.FAILED , plupload.DONE |
lastModifiedDate | 文件最后修改的時間 |
getNative() | 獲取原生的文件對象 |
getSource() | 獲取mOxie.File 對象,想了解mOxie是什么東西,可以看下https://github.com/moxiecode/moxie/wiki/API |
destroy() | 銷毀文件對象 |
六、QueueProgress 對象的屬性
plupload實例的total屬性是一個QueueProgress對象
屬性 | 描述 |
---|---|
size | 上傳隊列中所有文件加起來的總大小,單位為字節 |
loaded | 隊列中當前已上傳文件加起來的總大小,單位為字節 |
uploaded | 已完成上傳的文件的數量 |
failed | 上傳失敗的文件數量 |
queued | 隊列中剩下的(也就是除開已經完成上傳的文件)需要上傳的文件數量 |
percent | 整個隊列的已上傳百分比,如50就代表50% |
bytesPerSec | 上傳速率,單位為 byte/s,也就是 字節/秒 |
七、plupload命名空間上的一些屬性
plupload的命名空間上有一些屬性,用來表示一些常量。記住,不是plupload實例的屬性,而是plupload的屬性
屬性名稱 | 描述 |
---|---|
VERSION | 當前plupload的版本號 |
STOPPED | 值為1,代表上傳隊列還未開始上傳或者上傳隊列中的文件已經上傳完畢時plupload實例的state 屬性值 |
STARTED | 值為2,代表隊列中的文件正在上傳時plupload實例的state 屬性值 |
QUEUED | 值為1,代表某個文件已經被添加進隊列等待上傳時該文件對象的status 屬性值 |
UPLOADING | 值為2,代表某個文件正在上傳時該文件對象的status 屬性值 |
FAILED | 值為4,代表某個文件上傳失敗后該文件對象的status 屬性值 |
DONE | 值為5,代表某個文件上傳成功后該文件對象的status 屬性值 |
GENERIC_ERROR | 值為-100,發生通用錯誤時的錯誤代碼 |
HTTP_ERROR | 值為-200,發生http網絡錯誤時的錯誤代碼,例如服務氣端返回的狀態碼不是200 |
IO_ERROR | 值為-300,發生磁盤讀寫錯誤時的錯誤代碼,例如本地上某個文件不可讀 |
SECURITY_ERROR | 值為-400,發生因為安全問題而產生的錯誤時的錯誤代碼 |
INIT_ERROR | 值為-500,初始化時發生錯誤的錯誤代碼 |
FILE_SIZE_ERROR | 值為-600,當選擇的文件太大時的錯誤代碼 |
FILE_EXTENSION_ERROR | 值為-601,當選擇的文件類型不符合要求時的錯誤代碼 |
FILE_DUPLICATE_ERROR | 值為-602,當選取了重復的文件而配置中又不允許有重復文件時的錯誤代碼 |
IMAGE_FORMAT_ERROR | 值為-700,發生圖片格式錯誤時的錯誤代碼 |
IMAGE_MEMORY_ERROR | 當發生內存錯誤時的錯誤代碼 |
IMAGE_DIMENSIONS_ERROR | 值為-702,當文件大小超過了plupload所能處理的最大值時的錯誤代碼 |