Vue+elelemtUI实现断点续传(前端)
⼀、在config->index.js中设置 proxy
1 devServer: {
2 proxy: {
3 '/': {
4 target: '127.0.0.1:8888',
5 changeOrigin: true
6 }
7 }
8 }
⼆、下载并引⽤相应依赖(main.js)
本次demo是利⽤ Element-ui 配合开发。
所需依赖(我的版本):
"element-ui": "^2.13.2",
"axios": "^0.19.2",
"spark-md5": "^3.0.1",
"qs": "^6.9.4",
如果嫌⼀个⼀个下载⿇烦,可以把上⾯内容复制到 package.json 中 “dependencies” ,执⾏ "npm install" 即可。 main.js引⼊所需包:
1 import ElementUI from 'element-ui';
2 import 'element-ui/lib/theme-chalk/index.css';
3 Vue.use(ElementUI);
App.vue中引⼊所需包:
1 import { fileParse } from "./assets/utils";
2 import axios from "axios";
3 import SparkMD5 from "spark-md5";
三、HTML部分
使⽤Element-UI实现前端样式展⽰
1 <template>
2 <div id="app">
3 <el-upload drag action :auto-upload="false" :show-file-list="false" :on-change="changeFile">
4 <i class="el-icon-upload"></i>
5 <div class="el-upload__text">
6将⽂件拖到此处,或
7 <em>点击上传</em>
8 </div>
9 </el-upload>
10
11 <!-- PROGRESS -->
12 <div class="progress">
13 <span>上传进度:{{total|totalText}}%</span>
14 <el-link type="primary" v-if="total>0 && total<100" @click="handleBtn">{{btn|btnText}}</el-link>
15 </div>
16
17 <!-- VIDEO -->
18 <div class="uploadImg" v-if="video">
19 <video :src="video" controls />
20 </div>
21 </div>
22 </template>
四、使⽤ promise 封装 fileParse⽅法
promise:promise构造函数是同步执⾏的,并且是⽴即执⾏的函数,promise.then中的函数是异步的。并且promise状态改变后将不会再更改。
Promise有三个状态:pending(等待)、fulfilled(实现)、rejected(拒绝),其中resolve和reject只有第⼀次执⾏有效。
utils.js(对⽂件转义形式进⾏封装,根据所传⼊参数确定封装格式【base64、buffer】)
1 export function fileParse(file, type = "base64") {
2return new Promise(resolve => {
正则匹配哈希值3 let fileRead = new FileReader();
4if (type === "base64") {
5 adAsDataURL(file);
6 } else if (type === "buffer") {
7 adAsArrayBuffer(file);
8 }
9 load = (ev) => {
10 resolve(sult);
11 };
12 });
13 };
五、逻辑流程(前端)
1、利⽤结合promise封装filepase⽅法,解析⽂件为buffer数据
2、使⽤sparkMD5⽣成⽂件的哈希值,并获取后缀;使⽤spark.append(buffer)⽣成哈希值
3、通过正则获取⽂件后缀
4、创建切⾯默认参数,包括:切⽚个数、索引值和结束值
5、通过flie.slice()进⾏切⽚
6、进⾏遍历上传切⽚,判断当前索引 >= 切⽚数组后停⽌,调⽤合并⽂件接⼝告知服务器进⾏合并
六、项⽬整体代码
1 <script>
2 import { fileParse } from "./assets/utils";
3 import axios from "axios";
4 import SparkMD
5 from "spark-md5";
5
6 export default {
7 name: "App",
8 data() {
9return {
10 total: 0,
11 video: null,
12 btn: false,
13 };
14 },
15 filters: {
16 btnText(btn) {
17return btn ? "继续" : "暂停";
18 },
19 totalText(total) {
20return total > 100 ? 100 : total;
21 },
22 },
23 methods: {
24 async changeFile(file) {
25if (!file) return;
26 file = file.raw;
27
28// 解析为BUFFER数据
29// 我们会把⽂件切⽚处理:把⼀个⽂件分割成为好⼏个部分(固定数量/固定⼤⼩) 30// 每⼀个切⽚有⾃⼰的部分数据和⾃⼰的名字
31// HASH_1.mp4
32// HASH_2.mp4
33// ...
34 let buffer = await fileParse(file, "buffer"),
35 spark = new SparkMD5.ArrayBuffer(),
36 hash,
37 suffix;
38 spark.append(buffer);
39 hash = d();
40 suffix = /\.([0-9a-zA-Z]+)$/i.exec(file.name)[1];
41
42// 创建100个切⽚
43 let partList = [],
44 partsize = file.size / 100,
45 cur = 0;
46for (let i = 0; i < 100; i++) {
47 let item = {
48 chunk: file.slice(cur, cur + partsize),
49 filename: `${hash}_${i}.${suffix}`,
50 };
51 cur += partsize;
52 partList.push(item);
53 }
54
55this.partList = partList;
56this.hash = hash;
57this.sendRequest();
58 },
59 async sendRequest() {
60// 根据100个切⽚创造100个请求(集合)
61 let requestList = [];
62this.partList.forEach((item, index) => {
63// 每⼀个函数都是发送⼀个切⽚的请求
64 let fn = () => {
65 let formData = new FormData();
66 formData.append("chunk", item.chunk);
67 formData.append("filename", item.filename);
68return axios
69 .post("/single3", formData, {
70 headers: { "Content-Type": "multipart/form-data" },
71 })
72 .then((result) => {
73 result = result.data;
74if (de == 0) {
76// 传完的切⽚我们把它移除掉
77this.partList.splice(index, 1);
78 }
79 });
80 };
81 requestList.push(fn);
82 });
83
84// 传递:并⾏(ajax.abort())/串⾏(基于标志控制不发送)
85 let i = 0;
86 let complete = async () => {
87 let result = ("/merge", {
88 params: {
89 hash: this.hash,
90 },
91 });
92 result = result.data;
93if (de == 0) {
94this.video = result.path;
95 }
96 };
97 let send = async () => {
98// 已经中断则不再上传
99if (this.abort) return;
100if (i >= requestList.length) {
101// 都传完了
102 complete();
103return;
104 }
105 await requestList[i]();
106 i++;
107 send();
108 };
109 send();
110 },
111 handleBtn() {
112if (this.btn) {
113//断点续传
114this.abort = false; 115this.btn = false; 116this.sendRequest(); 117return;
118 }
119//暂停上传
120this.btn = true;
121this.abort = true; 122 },
123 },
124 };
125 </script>
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论