Using Web Uploader file upload component to assist Java to realize breakpoint continuation

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

WebUploader official website

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 nameParameter descriptiondescribe
dndAcceptitems {DataTransferItemList}DataTransferItemBlocking 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.
beforeFileQueuedfile {File}File objectTriggered 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.
fileQueuedfile {File}File objectTriggered when the file is added to the queue.
filesQueuedfiles {File} array, which contains the original File(lib/File) object.Triggered when a batch of files are added to the queue.
fileDequeuedfile {File}File objectTriggered when the file is removed from the queue.
resetTriggered when the uploader is reset.
startUploadTriggered when the upload process starts.
stopUploadTriggered when the upload process is suspended.
uploadFinishedTriggered when all files are uploaded.
uploadStartfile {File}File objectTriggered before a file starts uploading. A file will only be triggered once.
uploadBeforeSendobject {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.
uploadAcceptobject {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.
uploadProgressfile {File}File object

percentage {Number} upload progress
Triggered during the upload process, the upload progress is carried.
uploadErrorFile object {file}

reason {String} error code
Triggered when a file upload error occurs.
uploadSuccessfile {File}File object response {Object} data returned by the serverTriggered when the file is uploaded successfully.
uploadCompletefile {File} [optional] file objectTriggered when the file upload is completed, regardless of success or failure.
errortype {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:&nbsp;&nbsp; {{file.name}}</span>&nbsp;&nbsp;&nbsp;&nbsp;
      <span>File type:&nbsp;&nbsp; {{file.ext}}</span>&nbsp;&nbsp;&nbsp;&nbsp;
      <span >Upload progress:&nbsp;&nbsp; {{percentage}}%</span>&nbsp;&nbsp;&nbsp;&nbsp;
      <button @click="start(file)">start </button>&nbsp;&nbsp;&nbsp;&nbsp;
      <button @click="stop(file)">suspend </button>&nbsp;&nbsp;&nbsp;&nbsp;
      <button @click="removeFile(file)">delete</button>&nbsp;&nbsp;&nbsp;&nbsp;
    </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>

Keywords: Java Front-end IDE

Added by simwiz on Sat, 12 Feb 2022 06:09:26 +0200