1, Breakpoint continuation
Breakpoint continuation overview
Breakpoint continuation means that when downloading or uploading, the download or upload task is divided into several parts, and each part is uploaded or downloaded by one thread. In case of network failure, you can continue to upload and download the unfinished part from the part that has been uploaded or downloaded, instead of uploading and downloading from the beginning. Breakpoint continuation can improve and save operation time, Improve user experience.
Upload process:
1,Divide the file into blocks before uploading 2,Upload piece by piece. After the upload is interrupted, upload again. The uploaded blocks do not need to be uploaded again 3,Each block upload completes the final merged file
File blocking
The process of file blocking is as follows:
1,Get source file length 2,Calculate the number of blocks according to the size of the set block file 3,Read data from the source file and write data to each block file in turn.
@Test public void testChunk() throws IOException { //source file File sourceFile = new File("D:\\video\\test.avi"); //Block file directory String chunkFileFolder = "D:\\video\\chunks\\"; //Define block file size long chunkFileSize = 2 * 1024 * 1024; //Number of blocks long chunkFileNum = (long) Math.ceil(sourceFile.length() * 1.0 /chunkFileSize); //Create objects that read files RandomAccessFile raf_read = new RandomAccessFile(sourceFile,"r"); //buffer byte[] b = new byte[1024]; for(int i=0;i<chunkFileNum;i++){ //Block file path File chunkFile = new File(chunkFileFolder+i); //Create a write object to a block file RandomAccessFile raf_write = new RandomAccessFile(chunkFile,"rw"); int len = -1; while((len = raf_read.read(b))!=-1){ raf_write.write(b,0,len); //If the size of the block file reaches 2M, start writing down a block if(chunkFile.length()>=chunkFileSize){ break; } } raf_write.close(); } raf_read.close(); }
File merge
Document consolidation process:
1,Find the files to be merged and sort them in the order in which they are merged. 2,Create merge file 3,The number of data read from the merged file in turn and written to the merged file
@Test public void testMergeFile() throws IOException { //Block file directory String chunkFileFolderPath = "D:\\video\\chunks\\"; //Block file directory object File chunkFileFolder = new File(chunkFileFolderPath); //Block file list File[] files = chunkFileFolder.listFiles(); //Turn into a set to facilitate sorting. Sort the block files in ascending order by name List<File> fileList = Arrays.asList(files); 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; } }); //Merge files File mergeFile = new File("D:\\video\\test_merge.avi"); //create a new file boolean newFile = mergeFile.createNewFile(); //Create write object RandomAccessFile raf_write = new RandomAccessFile(mergeFile,"rw"); byte[] b = new byte[1024]; for(File chunkFile:fileList){ //Create an object that reads a block file RandomAccessFile raf_read = new RandomAccessFile(chunkFile,"r"); int len = -1; while((len = raf_read.read(b))!=-1){ raf_write.write(b,0,len); } raf_read.close(); } raf_write.close(); }
2, Web Uploader
Overview of Web Uploader
WebUploader is a simple modern file upload component based on HTML5 and supplemented by FLASH developed by Baidu WebFE(FEX) team. In modern browsers, we can give full play to the advantages of HTML5 without abandoning the mainstream IE browser. We use the original FLASH runtime, which is compatible with IE6 +, iOS 6+, android 4 +. When the two sets are running, the same calling mode can be selected by users at will.
characteristic
Hook Method
There are many hook methods available in webuploader. The core hook methods are:
Registration hook method source code:
WebUploader.Uploader.register({ "before‐send‐file":"beforeSendFile", "before‐send":"beforeSend", "after‐send‐file":"afterSendFile" }
You need to create a webUploader object before using webUploader.
Specify the address of the upload block: / api/media/upload/uploadchunk
// Create an uploader object and configure parameters this.uploader = WebUploader.create( { swf:"/static/plugins/webuploader/dist/Uploader.swf",//The flash file of the uploaded file is started when the browser does not support h5 flash server:"/api/media/upload/uploadchunk",//Upload the server address of the block, and pay attention to the cross domain problem fileVal:"file",//name of file upload domain pick:"#picker ", / / specifies the button container for selecting files auto:false,//Manually trigger upload disableGlobalDnd:true,//Disable the drag and drop function of the whole page chunked:true,// Whether to upload in blocks chunkSize:1*1024*1024, // Block size (default 5M) threads:3, // Open multiple threads (3 by default) prepareNextFile:true// Allow the next file to be prepared in advance during file transfer } )
Before send file: before file uploading, the front end requests the server to prepare for uploading
type:"POST", url:"/api/media/upload/register", data:{ // File unique representation fileMd5:this.fileMd5, fileName: file.name, fileSize:file.size, mimetype:file.type, fileExt:file.ext }
Before send: before uploading the block, the front end requests the server to verify whether the block exists.
type:"POST", url:"/api/media/upload/checkchunk", data:{ // File unique representation fileMd5:this.fileMd5, // Current block subscript chunk:block.chunk, // Current block size chunkSize:block.end‐block.start }
After send file: triggered after all block uploads are completed, you can request the server to merge the block files
type:"POST", url:"/api/media/upload/mergechunks", data:{ fileMd5:this.fileMd5, fileName: file.name, fileSize:file.size, mimetype:file.type, fileExt:file.ext }
event
Event name | Parameter description | describe |
---|---|---|
dndAccept | items {DataTransferItemList}DataTransferItem | Blocking this event can deny certain types of files from being dragged in. At present, only chrome provides such an API, which can only be verified by MIME type. |
beforeFileQueued | file {File}File object | Triggered before the file is added to the queue, and the handler return value of this event is false, the file will not be added to the queue. |
fileQueued | file {File}File object | Triggered when the file is added to the queue. |
filesQueued | files {File} array, which contains the original File(lib/File) object. | Triggered when a batch of files are added to the queue. |
fileDequeued | file {File}File object | Triggered when the file is removed from the queue. |
reset | Triggered when the uploader is reset. | |
startUpload | Triggered when the upload process starts. | |
stopUpload | Triggered when the upload process is suspended. | |
uploadFinished | Triggered when all files are uploaded. | |
uploadStart | file {File}File object | Triggered before a file starts uploading. A file will only be triggered once. |
uploadBeforeSend | object {Object} data {Object} is the default upload parameter. This object can be extended to control upload parameters. headers {Object} can extend this object to control upload headers. | When the fragmentation of a file is triggered before sending, it is mainly used to ask whether to add attached parameters. This event may be triggered multiple times on the premise of fragment upload of large files. |
uploadAccept | object {Object} ret {Object} the returned data of the server, in json format. If the server is not in json format, start from ret_ Take data from raw and analyze it by yourself. | When a file is uploaded to the server for response, this event will be sent to ask whether the server response is valid. If the return value of this event handler is false, this file will send an uploadError event of server type. |
uploadProgress | file {File}File object percentage {Number} upload progress | Triggered during the upload process, the upload progress is carried. |
uploadError | File object {file} reason {String} error code | Triggered when a file upload error occurs. |
uploadSuccess | file {File}File object response {Object} data returned by the server | Triggered when the file is uploaded successfully. |
uploadComplete | file {File} [optional] file object | Triggered when the file upload is completed, regardless of success or failure. |
error | type {String} wrong type. | When the validate fails, the caller will be notified in the form of sending an error event. Through upload On ('error ', handler) can catch such errors. At present, the following errors will be sent under specific circumstances. Q_EXCEED_NUM_LIMIT is dispatched when fileNumLimit is set and the number of files trying to add to uploader exceeds this value. Q_EXCEED_SIZE_LIMIT set Q in_ EXCEED_ SIZE_ Limit and try to add files to uploader when the total size exceeds this value. Q_TYPE_DENIED triggered when the file type is not satisfied.. |
3, Server implementation function
1. Check the upload environment before uploading
Check whether the file is uploaded. If it has been uploaded, return directly. Check whether the file upload path exists. If it does not exist, create it.
2. Block inspection
Check whether the block file is uploaded, and return if it has been uploaded true. If it is not uploaded, check whether the upload path exists. If it does not exist, create it.
3. Block upload
Upload the block file to the specified path.
4. Merge block
Merge all block files into one file. Record file information in the database.
FileUploadController
@RestController @RequestMapping("/upload") public class FileUploadController { @Autowired private IFileUploadService fileUploadService; //Registration before file upload @PostMapping("/register") public Object register(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt) { return fileUploadService.register(fileMd5,fileName,fileSize,mimetype,fileExt); } //Block inspection @PostMapping("/checkchunk") public Object checkchunk(String fileMd5, Integer chunk, Integer chunkSize) { return fileUploadService.checkchunk(fileMd5,chunk,chunkSize); } //Upload block @PostMapping("/uploadchunk") public Object uploadchunk(MultipartFile file, String fileMd5, Integer chunk) { return fileUploadService.uploadchunk(file,fileMd5,chunk); } //Merge files @PostMapping("/mergechunks") public Object mergechunks(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt) { return fileUploadService.mergechunks(fileMd5,fileName,fileSize, mimetype,fileExt); } }
IFileUploadService
public interface IFileUploadService { /** * Check whether the file exists before uploading * * Get the file path according to file md5 * * @param fileMd5 File md5 value * @param fileName file name * @param fileSize file size * @param mimetype file type * @param fileExt File extension * @return */ Object register(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt); /** * Block file check * @param fileMd5 File md5 * @param chunk Block file subscript * @param chunkSize Block file size * @return */ Object checkchunk(String fileMd5, Integer chunk, Integer chunkSize); /** * Upload block file * @param file File object * @param fileMd5 File md5 * @param chunk Block file subscript * @return */ Object uploadchunk(MultipartFile file, String fileMd5, Integer chunk); /** * Merge block files * @param fileMd5 File md5 * @param fileName file name * @param fileSize file size * @param mimetype file type * @param fileExt File extension * @return */ Object mergechunks(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt); }
FileUploadServiceImpl
@Service public class FileUploadServiceImpl implements IFileUploadService { @Value("${fileUploadPaht}") String uploadPath; @Override public Object register(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt) { //Check whether the file exists on the disk //The path to the directory to which the file belongs String fileFolderPath = this.getFileFolderPath(fileMd5); //File path String filePath = this.getFilePath(fileMd5, fileExt); File file = new File(filePath); //Does the file exist boolean exists = file.exists(); //TODO checks whether the file information in the database exists //If the file does not exist, check whether the directory where the file is located exists. If it does not exist, create it File fileFolder = new File(fileFolderPath); if (!fileFolder.exists()) { fileFolder.mkdirs(); } HashMap map = new HashMap<String, Integer>(); map.put("ok", 1); return map; } @Override public Object checkchunk(String fileMd5, Integer chunk, Integer chunkSize) { //Get the directory where the block file is located String chunkFileFolderPath = this.getChunkFileFolderPath(fileMd5); //Get block file File chunkFile = new File(chunkFileFolderPath + chunk); //Check whether the block file exists if (chunkFile.exists()) { //Block file exists return BaseUtil.back(1, ""); } else { //Block file does not exist return BaseUtil.back(0, ""); } } @Override public Object uploadchunk(MultipartFile file, String fileMd5, Integer chunk) { //Get block file directory String chunkFileFolderPath = this.getChunkFileFolderPath(fileMd5); //Get block file path String chunkFilePath = chunkFileFolderPath + chunk; //Check the partition directory. If it does not exist, it should be created automatically File chunkFileFolder = new File(chunkFileFolderPath); if (!chunkFileFolder.exists()) { chunkFileFolder.mkdirs(); } //Get the input stream of the uploaded file InputStream inputStream = null; FileOutputStream outputStream = null; try { inputStream = file.getInputStream(); outputStream = new FileOutputStream(new File(chunkFilePath)); IOUtils.copy(inputStream, outputStream); } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return BaseUtil.back(1, ""); } @Override public Object mergechunks(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt) { //Get the directory of the block file String chunkFileFolderPath = this.getChunkFileFolderPath(fileMd5); File chunkFileFolder = new File(chunkFileFolderPath); //Get the block file list File[] files = chunkFileFolder.listFiles(); List<File> fileList = Arrays.asList(files); //Create merge file path String filePath = this.getFilePath(fileMd5, fileExt); File mergeFile = new File(filePath); //Perform merge mergeFile = this.mergeFile(fileList, mergeFile); if (mergeFile == null) { //Failed to merge files BaseUtil.back(0, ""); } //Verify whether the md5 value of the file is consistent with the md5 value passed in from the front end boolean checkFileMd5 = this.checkFileMd5(mergeFile, fileMd5); if (!checkFileMd5) { //Failed to verify file BaseUtil.back(0, ""); } //TODO writes the information of the file to the database String file_id = fileMd5; String file_name = fileName; String file_name_ext = fileMd5 + "." + fileExt; //File path save relative path String file_path = fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + fileMd5 + "." + fileExt; ; Long file_size = fileSize; String file_type = mimetype; String file_ext = fileExt; return BaseUtil.back(1, ""); } /** * Verify the integrity of the file * * @param mergeFile * @param md5 * @return */ private boolean checkFileMd5(File mergeFile, String md5) { try { //Create file input stream FileInputStream inputStream = new FileInputStream(mergeFile); //Get md5 of the file String md5Hex = DigestUtils.md5Hex(inputStream); //Compare with incoming md5 if (md5.equalsIgnoreCase(md5Hex)) { return true; } } catch (Exception e) { e.printStackTrace(); return false; } return false; } /** * File merge * * @param chunkFileList * @param mergeFile * @return */ private File mergeFile(List<File> chunkFileList, File mergeFile) { try { //Delete if the merged file already exists, otherwise create a new file if (mergeFile.exists()) { mergeFile.delete(); } else { //Create a new file mergeFile.createNewFile(); } //Sort block files Collections.sort(chunkFileList, new Comparator<File>() { @Override public int compare(File o1, File o2) { if (Integer.parseInt(o1.getName()) > Integer.parseInt(o2.getName())) { return 1; } return -1; } }); //Create a write object RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw"); byte[] b = new byte[1024]; for (File chunkFile : chunkFileList) { RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "r"); int len = -1; while ((len = raf_read.read(b)) != -1) { raf_write.write(b, 0, len); } raf_read.close(); } raf_write.close(); return mergeFile; } catch (IOException e) { e.printStackTrace(); return null; } } /** * Get the directory path to which the file belongs * * @param fileMd5 File md5 value * @return */ private String getFileFolderPath(String fileMd5) { return uploadPath + fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/"; } /** * Get the path of the file * * @param fileMd5 File md5 value * @param fileExt File extension * @return */ private String getFilePath(String fileMd5, String fileExt) { return uploadPath + fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + fileMd5 + "." + fileExt; } /** * Get the directory path where the block file is located * * @param fileMd5 * @return */ private String getChunkFileFolderPath(String fileMd5) { return uploadPath + fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/chunk/"; } }
public class BaseUtil { private int code; private String msg; public static HashMap<Object,Object> back(int code, String msg){ HashMap<Object, Object> map = new HashMap<>(); map.put("id",code); map.put("msg",msg); return map; } }
4, Use of Web Uploader
Introducing webuploader
Direct import file
<!--introduce CSS--> <link rel="stylesheet" type="text/css" href="webuploader folder/webuploader.css"> <!--introduce JQuery--> <script type="text/javascript" src="JQuery folder/JQuery.js"></script> <!--introduce JS--> <script type="text/javascript" src="webuploader folder/webuploader.js"></script>
Modular introduction
Download and install the corresponding integration module
npm install webuploader --save npm install jquery --save
Enter webploder and jquery
import $ from 'jquery' import WebUploader from 'webuploader'
Initialize webuploader
// Initialize the webuploader, create the uploader object, and configure the parameters this.uploader = WebUploader.create( { //The flash file of the uploaded file. When the browser does not support h5, start flash swf: './Uploader.swf', //Upload the partitioned server address, pay attention to the cross domain problem, and write the path of the Or agent forwarding request server: "http://localhost:8080/zhunda-training-api/training/upload/uploadchunk" , //Is it allowed to carry cookie s across domains withCredentials: true, //name of file upload domain fileVal:"file", //Specifies the button container for selecting files pick:"#picker", //Manually trigger upload auto:false, //Disable the drag and drop function of the whole page disableGlobalDnd:true, //Open slice upload chunked:true, //Block size (default 5M) chunkSize:1*1024*1024, //Open multiple threads (3 by default) threads:3, //Allow the next file to be prepared in advance during file transfer prepareNextFile:true } );
Triggered after selecting a file
//Triggered after selecting a file this.uploader.on("beforeFileQueued", function(file) { // this.uploader.removeFile(file) //Reset uploader console.log(file) this.uploader.reset() this.percentage = 0; }.bind(this));
Add file to queue
// Add file to queue this.uploader.on("fileQueued", function(file) { console.log("Add file to queue") this.fileList.push(file); var $list = $('#fileList') $list.append( '<div id="' + file.id + '" class="item">' + '<h4 class="info">' + file.name + '</h4>' + '<p class="state">Waiting for upload...</p>' + '</div>' ); this.uploadFile=file; this.percentage = 0; }.bind(this) );
Upload failure: uploadError
//Upload failure trigger this.uploader.on("uploadError", function(file,reason) { console.log(reason) alert("Failed to upload file"); });
Upload success: uploadSuccess
//Upload successfully triggered this.uploader.on("uploadSuccess", function(file,res ) { console.log(res) alert("Upload file succeeded!"); });
Upload progress: upload progress monitoring
// Monitor upload progress // Percentage: represents the percentage of uploaded files this.uploader.on("uploadProgress", function(file, percentage) { console.log("Monitor upload progress") this.percentage = Math.ceil(percentage * 100); }.bind(this));
//Triggered after each block upload request this.uploader.on( 'uploadAccept', function( file, res ) { console.log("Triggered after each block upload request") if(res.code===0){//Upload block failed return false; } });
Demo example
<template> <div id="app"> <div id="uploader" class="wu-example"> <!-- Button to select a file --> <div class="btns" style="float:left;padding-right: 20px"> <div id="picker">Select file</div> </div> <!-- Start upload button --> <div id="ctlBtn" class="webuploader-pick" @click="upload()">Start uploading</div> </div> <!--Used to store file information--> <div v-for="(file,index) in fileList" :key="index" id="fileLilst" class="uploader-list" :class="`file-${file.id}`"> <span>File name: {{file.name}}</span> <span>File type: {{file.ext}}</span> <span >Upload progress: {{percentage}}%</span> <button @click="start(file)">start </button> <button @click="stop(file)">suspend </button> <button @click="removeFile(file)">delete</button> </div> </div> </template> <script> import $ from 'jquery' import WebUploader from 'webuploader' export default { name: 'App', data(){ return{ uploader:{}, uploadFile:{}, percentage:0, fileMd5:'', fileList:[], } }, created() { console.log($) }, methods:{ //Start uploading upload(){ if(this.fileList.length>0){ this.fileList.forEach(file =>{ this.uploader.upload(file); }) }else{ alert("Please select a file"); } }, start(file){ this.uploader.upload(file); }, //Pause file upload stop(file) { this.uploader.stop(file); }, // Remove file from queue removeFile(file) { // Cancel and interrupt file upload this.uploader.cancelFile(file,true); // Remove file from queue this.uploader.removeFile(file); //Interface removal this.fileList=this.fileList.filter(item => item.id!==file.id) }, }, mounted(){ let that = this; //Check whether the document is put on let beforeSendFile=function(file){ //Create a deferred object, which is often used in the hook return function to handle asynchronous operations that need to wait. // Do some asynchronous operations before sending the file. // WebUploader will wait for this asynchronous operation to complete before sending the file. var deferred = WebUploader.Deferred(); //Calculate the md5 value of the file, which is used for continuous transmission at breakpoints, and return a promise object, which can monitor the progress progress (new WebUploader.Uploader()).md5File(file) .then(function(val) { that.fileMd5=val that.uploadFile = file; //Packaging parameters let searchParams = new URLSearchParams(); searchParams.append("fileMd5",that.fileMd5); searchParams.append("fileName", file.name); searchParams.append("fileSize",file.size); searchParams.append("mimetype",file.type); searchParams.append("fileExt",file.ext); //Request the server to register and upload files that.axios.post(that.$Api.webUploader.register,searchParams).then(res =>{ if (res.data.code===1){ //alert('upload file registration succeeded, start uploading '); console.log("Initialization preparation completed") deferred.resolve(); }else{ // alert("upload file registration failed"); deferred.reject(); console.log("Initialization preparation failed") } }) }.bind(that)); return deferred.promise(); }; //Check blocks before uploading blocks every time. If blocks already exist, they will not be uploaded again, so as to achieve the purpose of continuous transmission at breakpoints let beforeSend=function(block){ var deferred = WebUploader.Deferred(); //Encapsulation request parameters let searchParams = new URLSearchParams(); // File unique representation searchParams.append("fileMd5",that.fileMd5); // Current block subscript searchParams.append("chunk",block.chunk); // Current block size searchParams.append("chunkSize",block.end-block.start); that.axios.post(that.$Api.webUploader.checkchunk,searchParams).then(res =>{ if (res.data.code===1){ // Block exists, skip this block deferred.reject(); console.log("Block exists, skip this block") }else{ // Block does not exist or is incomplete, resend deferred.resolve(); console.log("Block does not exist or is incomplete, resend") } }) //Build the fileMd5 parameter and bring fileMd5 when uploading blocks that.uploader.options.formData.fileMd5 = that.fileMd5; that.uploader.options.formData.chunk = block.chunk; return deferred.promise(); }; // Merge block let afterSendFile=function(file){ //Encapsulation request parameters let searchParams = new URLSearchParams(); searchParams.append("fileMd5",that.fileMd5); searchParams.append("fileName",file.name); searchParams.append("fileSize",file.size); searchParams.append("mimetype",file.type); searchParams.append("fileExt",file.ext); that.axios.post(that.$Api.webUploader.mergechunks,searchParams).then(res =>{ if (res.data.code===1){ console.log("File merge succeeded") }else{ console.log("File merge failed") } }) }; /** * Uploader.register(map, proto); * * responseMap {object}API Mapping between name and function implementation * proto {object}Component prototype. The constructor adds components through the constructor attribute definition */ WebUploader.Uploader.register({ "before-send-file":"beforeSendFile", "before-send":"beforeSend", "after-send-file":"afterSendFile" },{beforeSendFile, beforeSend, afterSendFile,} ); // Create an uploader object and configure parameters this.uploader = WebUploader.create( { //The flash file of the uploaded file. When the browser does not support h5, start flash swf: '../node_modules/webuploader/dist/Uploader.swf', //Upload the partitioned server address, pay attention to the cross domain problem, and write the path of the Or agent forwarding request server: "http://localhost:8080/zhunda-training-api/training/upload/uploadchunk" , //Is it allowed to carry cookie s across domains withCredentials: true, //name of file upload domain fileVal:"file", //id: Specifies the button container for selecting files. If it is not specified, the button will not be created. Multiple: whether to enable the ability to select multiple files at the same time pick:{id:"#picker",multiple:true }, //Whether to upload files automatically after selecting them auto:false, //Disable the drag and drop function of the whole page disableGlobalDnd:true, //Fragment upload chunked:true, //Repeat upload duplicate: false, //Block size (default 5M) chunkSize:1*1024*1024, //Open multiple threads (3 by default) threads:3, // Limit the number of uploads fileNumLimit: 3, //Allow the next file to be prepared in advance during file transfer prepareNextFile:true, //Specifies which types of files are accepted. Need to be specified separately. //title {String} text description //extensions {String} allows file suffixes without dots. Multiple suffixes are separated by commas. //mimeTypes {String} are separated by commas. accept:[{title: 'file', extensions: 'mp4,avi', mimeTypes: 'video/*'}], } ); // Add file to queue this.uploader.on("fileQueued", function(file) { console.log("Add file to queue "") this.uploadFile=file; this.fileList.push(file); }.bind(this) ); //Triggered after selecting a file this.uploader.on("beforeFileQueued", function(file) { // this.uploader.removeFile(file) //Reset uploader console.log(file) //this.uploader.reset() }.bind(this)); // Monitor upload progress // percentage:Represents the percentage of uploaded files this.uploader.on("uploadProgress", function(file, percentage) { console.log('Monitor upload progress', file,percentage) this.percentage = Math.ceil(percentage * 100); }.bind(this)); //Upload failure trigger this.uploader.on("uploadError", function(file,reason) { console.log(reason) alert("Failed to upload file ""); }); //Upload successfully triggered this.uploader.on("uploadSuccess", function(file,res ) { console.log(res) //alert("Upload file succeeded! "); }); //Triggered after each block upload request this.uploader.on( 'uploadAccept', function( file, res ) { console.log("Triggered after each block upload request ") if(res.code===0){//Block upload failed return false; } }); } } </script> <style > .webuploader-container { position: relative; } .webuploader-element-invisible { position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px,1px,1px,1px); } .webuploader-pick { position: relative; display: inline-block; cursor: pointer; background: #00b7ee; padding: 10px 15px; color: #fff; text-align: center; border-radius: 3px; overflow: hidden; } .webuploader-pick-hover { background: #00a2d4; } .webuploader-pick-disable { opacity: 0.6; pointer-events:none; } </style>