Home >Web Front-end >JS Tutorial >How to implement the file upload function in slices through Vue2.0 combined with webuploader (detailed tutorial)

How to implement the file upload function in slices through Vue2.0 combined with webuploader (detailed tutorial)

亚连
亚连Original
2018-05-31 15:58:516205browse

This article mainly introduces the function of Vue2.0 combined with webuploader to implement file segmentation upload. It is very good and has reference value. Friends in need can refer to it

Encountered large file segmentation in the Vue project Regarding the upload problem, I have used webuploader before, so I simply combined Vue2.0 with webuploader to encapsulate a vue upload component, which is more comfortable to use.

Upload, just upload it. Why is it so troublesome to upload in parts?

The combination of fragmentation and concurrency splits a large file into multiple blocks and uploads them concurrently, which greatly improves the upload speed of large files.

When network problems cause transmission errors, only the error fragments need to be retransmitted, not the entire file. In addition, fragmented transmission can track the upload progress in more real-time.

The interface after implementation:

There are mainly two files, the encapsulated upload component and the specific ui page. The upload component code is listed below. The codes of these two pages are put on github: https://github.com/shady-xia/Blog/tree/master/vue-webuploader.

Introduce webuploader into the project

1. First introduce jquery into the system (the plug-in is based on jq, it’s a scam!), if you don’t If you know where to put it, put it in index.html.

2. Download Uploader.swf and webuploader.min.js on the official website, which can be placed under the static directory of the project; introduce webuploader in index.html .min.js.

(无需单独再引入 webuploader.css ,因为没有几行css,我们可以复制到vue组件中。)
<script src="/static/lib/jquery-2.2.3.min.js"></script>
<script src="/static/lib/webuploader/webuploader.min.js"></script>

Points to note:

1. In the vue component, pass import './webuploader' ; import webuploader, the error 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode...' will be reported. This is because your babel uses Strict mode, and callers are prohibited from being used in strict mode. Therefore, you can directly introduce webuploader.js into index.html, or manually solve the 'use strict' problem in babel.

Encapsulating Vue components based on webuploader

The encapsulated component upload.vue is as follows. The interface can be expanded according to specific business.

Note: Function and UI are separated. This component encapsulates the basic functions and does not provide UI. The UI is implemented on specific pages.

<template>
 <p class="upload">
 </p>
</template>
<script>
 export default {
  name: &#39;vue-upload&#39;,
  props: {
   accept: {
    type: Object,
    default: null,
   },
   // 上传地址
   url: {
    type: String,
    default: &#39;&#39;,
   },
   // 上传最大数量 默认为100
   fileNumLimit: {
    type: Number,
    default: 100,
   },
   // 大小限制 默认2M
   fileSingleSizeLimit: {
    type: Number,
    default: 2048000,
   },
   // 上传时传给后端的参数,一般为token,key等
   formData: {
    type: Object,
    default: null
   },
   // 生成formData中文件的key,下面只是个例子,具体哪种形式和后端商议
   keyGenerator: {
    type: Function,
    default(file) {
     const currentTime = new Date().getTime();
     const key = `${currentTime}.${file.name}`;
     return key;
    },
   },
   multiple: {
    type: Boolean,
    default: false,
   },
   // 上传按钮ID
   uploadButton: {
    type: String,
    default: &#39;&#39;,
   },
  },
  data() {
   return {
    uploader: null
   };
  },
  mounted() {
   this.initWebUpload();
  },
  methods: {
   initWebUpload() {
    this.uploader = WebUploader.create({
     auto: true, // 选完文件后,是否自动上传
     swf: &#39;/static/lib/webuploader/Uploader.swf&#39;, // swf文件路径
     server: this.url, // 文件接收服务端
     pick: {
      id: this.uploadButton,  // 选择文件的按钮
      multiple: this.multiple, // 是否多文件上传 默认false
      label: &#39;&#39;,
     },
     accept: this.getAccept(this.accept), // 允许选择文件格式。
     threads: 3,
     fileNumLimit: this.fileNumLimit, // 限制上传个数
     //fileSingleSizeLimit: this.fileSingleSizeLimit, // 限制单个上传图片的大小
     formData: this.formData, // 上传所需参数
     chunked: true,   //分片上传
     chunkSize: 2048000, //分片大小
     duplicate: true, // 重复上传
    });
    // 当有文件被添加进队列的时候,添加到页面预览
    this.uploader.on(&#39;fileQueued&#39;, (file) => {
     this.$emit(&#39;fileChange&#39;, file);
    });
    this.uploader.on(&#39;uploadStart&#39;, (file) => {
     // 在这里可以准备好formData的数据
     //this.uploader.options.formData.key = this.keyGenerator(file);
    });
    // 文件上传过程中创建进度条实时显示。
    this.uploader.on(&#39;uploadProgress&#39;, (file, percentage) => {
     this.$emit(&#39;progress&#39;, file, percentage);
    });
    this.uploader.on(&#39;uploadSuccess&#39;, (file, response) => {
     this.$emit(&#39;success&#39;, file, response);
    });
    this.uploader.on(&#39;uploadError&#39;, (file, reason) => {
     console.error(reason);
     this.$emit(&#39;uploadError&#39;, file, reason);
    });
    this.uploader.on(&#39;error&#39;, (type) => {
     let errorMessage = &#39;&#39;;
     if (type === &#39;F_EXCEED_SIZE&#39;) {
      errorMessage = `文件大小不能超过${this.fileSingleSizeLimit / (1024 * 1000)}M`;
     } else if (type === &#39;Q_EXCEED_NUM_LIMIT&#39;) {
      errorMessage = &#39;文件上传已达到最大上限数&#39;;
     } else {
      errorMessage = `上传出错!请检查后重新上传!错误代码${type}`;
     }
     console.error(errorMessage);
     this.$emit(&#39;error&#39;, errorMessage);
    });
    this.uploader.on(&#39;uploadComplete&#39;, (file, response) => {
     this.$emit(&#39;complete&#39;, file, response);
    });
   },
   upload(file) {
    this.uploader.upload(file);
   },
   stop(file) {
    this.uploader.stop(file);
   },
   // 取消并中断文件上传
   cancelFile(file) {
    this.uploader.cancelFile(file);
   },
   // 在队列中移除文件
   removeFile(file, bool) {
    this.uploader.removeFile(file, bool);
   },
   getAccept(accept) {
    switch (accept) {
     case &#39;text&#39;:
      return {
       title: &#39;Texts&#39;,
       exteensions: &#39;doc,docx,xls,xlsx,ppt,pptx,pdf,txt&#39;,
       mimeTypes: &#39;.doc,docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt&#39;
      };
      break;
     case &#39;video&#39;:
      return {
       title: &#39;Videos&#39;,
       exteensions: &#39;mp4&#39;,
       mimeTypes: &#39;.mp4&#39;
      };
      break;
     case &#39;image&#39;:
      return {
       title: &#39;Images&#39;,
       exteensions: &#39;gif,jpg,jpeg,bmp,png&#39;,
       mimeTypes: &#39;.gif,.jpg,.jpeg,.bmp,.png&#39;
      };
      break;
     default: return accept
    }
   },
  },
 };
</script>
<style lang="scss">
// 直接把官方的css粘过来就行了
</style>

Use the encapsulated upload component

Create a new page. The usage examples are as follows:

ui needs to be implemented by yourself. The approximate code can be found here.

<vue-upload
    ref="uploader"
    url="xxxxxx"
    uploadButton="#filePicker"
    multiple
    @fileChange="fileChange"
    @progress="onProgress"
    @success="onSuccess"
></vue-upload>

The principle and process of fragmentation

When we upload a large file, it will be fragmented by the plug-in, and the ajax request is as follows:

1. Multiple upload requests are all fragmented requests. The large file is divided into multiple small parts and delivered to the server one at a time

2. fragmentation After completion, that is, after the upload is completed, a merge request needs to be passed to the server to let the server combine multiple fragmented files into one file
Fragmentation

You can see that multiple upload requests have been initiated. We Let’s take a look at the specific parameters sent by upload:

The guid in the first configuration ( content-disposition ) and the access_token in the second configuration , it is the formData in the webuploader configuration, that is, the parameters passed to the server

The following configurations are the file content, id, name, type, size, etc.

chunks is the total fragmentation number, chunk is the current fragment. They are 12 and 9 respectively in the picture. When you see an upload request with chunk 11, it means that this is the last upload request.

Merge

After sharding, the files have not been integrated, and the data probably looks like the following:

After completing the sharding, the work is not over yet. We have to send another ajax request to the server, telling him to merge the several shards we uploaded into a complete file.

How do I know that the multipart upload is complete and when should I merge it?

webuploaderThe plug-in has an event uploadSuccess , which contains two parameters, file and response returned by the background; when all fragments are uploaded, this event will be triggered ,

We can use the fields returned by the server to determine whether to merge.

For example, needMerge is returned in the background. When we see that it is true, we can send a merge request.

Known issues

When pausing and continuing to upload a single file, a bug in this plug-in was discovered:

1 . When the set threads>1 is used and the single file upload function is used, that is, when the stop method is passed in file, an error Uncaught TypeError: Cannot read property 'file' of undefined

will be reported.

The source code of the error is as follows: This is because in order to allow the next file to continue to be transferred during the pause, the paused file stream will be popped out of the current pool. A loop is made here, and v is undefined during the last loop.

2. Set threads to 1 and it can be paused normally, but uploading after pausing will fail.

The principle is the same as the previous one. During the pause, all current file streams are popped in the pool. When the file starts to be uploaded, the current pool will be checked. At this time, there are no previously paused file streams.

If it is to pause and continue all files as a whole, the function is normal.

The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.

Related articles:

In-depth understanding of Node module module

Summary of 10 advanced techniques for using Console to debug

About the difference between v-if and v-show in vuejs and the problem that v-show does not work

The above is the detailed content of How to implement the file upload function in slices through Vue2.0 combined with webuploader (detailed tutorial). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn