赞
踩
1、前言
目前的element-ui在上传大文件时会出现上传失败的问题,项目希望实现大文件断点续传,秒传等功能。之前在TP项目下使用webuploader上传插件,文件服务器用PHP编写的。由于久不维护,决定使用vue-simple-uploader实现,文件服务器使用golang编写。
2、安装
npm install vue-simple-uploader --save
main.js引用:
md5工具安装:
npm install spark-md5 --save
在当前目录引用:
3、使用
- <div
- class="upload-box"
- v-if="checkBtnMp4()"
- >
- <div>
- <span class="title">上传视频</span>至多1个,不大于600M,支持格式:MP4
- </div>
- <uploader
- ref="upload"
- class="uploader-example"
- :options="options"
- :autoStart="true"
- :file-status-text="statusText"
- @file-success="success_video"
- @file-added="filesAdded"
- @file-progress="fileProgress"
- @file-error="onFileError"
- @file-removed="videoRemove"
- >
- <uploader-unsupport></uploader-unsupport>
- <uploader-drop>
- <uploader-btn
- :single="true"
- :attrs="attrs2"
- >点击上传</uploader-btn>
- </uploader-drop>
- <uploader-list v-show="panelShow"></uploader-list>
- </uploader>
- <ul
- class="el-upload-list el-upload-list--text success-video"
- v-if="show_filename && fileListMp4"
- >
- <li
- tabindex="0"
- class="el-upload-list__item is-success"
- v-for="(item, i) in fileListMp4"
- :key="i"
- >
- <a class="el-upload-list__item-name">
- <i class="el-icon-video-play"></i>
- {{item.filename}}
- </a>
- <label class="el-upload-list__item-status-label">
- <i class="el-icon-upload-success el-icon-circle-check"></i>
- </label>
- <i
- class="el-icon-close"
- @click="delMp4()"
- ></i>
- </li>
- </ul>
- </div>
- export default {
- name: "XXX",
- data() {
- return {
- isUploadOk: true, // 是否还有未上传完成的文件
- // 视频
- FileLimit: {
- FileMaxSize: 600, // 允许上传的大小 单位(G)
- FileFormat: ["mp4"], // 允许上传的格式
- FileUnit: "M" // 单位
- },
- panelShow: true, // 展示上传panel
- show_filename: true, //是否显示文件列表
- fileListMp4: [], // 视频格式数据
- uploadUrl: "", // 文件上传地址
- uploadData: "", // 文件上传参数
- options: {
- target: url.uploadPath, // 上传地址
- testChunks: false,
- singleFile: true, // 启用单个文件上传。上传一个文件后,第二个文件将超过现有文件,第一个文件将被取消。
- chunkSize: "1048576" * 1, //分块大小 单位(M)
- //下面参数文件服务器验证用
- query: {
- //传参
- UserId: localStorage.getItem("ms_userid"),
- SessionKey: localStorage.getItem("ms_token"),
- OS: 4,
- PluginType: 1
- }
- },
- //上传状态
- statusText: {
- success: "上传成功!",
- error: "出错了!",
- uploading: "上传中...",
- paused: "等待中...",
- waiting: "等待中..."
- },
- attrs2: {
- accept: ".mp4" //允许上传的格式
- }
- };
- }
-
4、上传流程
filesAdded:添加一个文件时的钩子。
progress:上传中的钩子。
onFileError:上传错误触发。
videoRemove:视频移除。
success_video:成功上传触发方法。
- // 添加一个文件时触发
- async filesAdded(file) {
- var FileLimit = this.FileLimit;
- const isFormat = this.checkExtensions(file.name, FileLimit.FileFormat); // 文件格式判断
- if (!isFormat) {
- file.ignored = true; // 过滤文件
- file.cancel(); // 停止上传
- return false;
- }
-
- // 文件大小判断
- const isSize = this.checkSize(file.size);
- if (!isSize) {
- file.ignored = true; // 过滤文件
- file.cancel(); // 停止上传
- return false;
- } else {
- this.panelShow = true; // 展示上传panel
- this.show_filename = false; // 不显示文件名
- this.computeMD5(file); // md5验证
- }
- },
- // 检查文件大小
- checkSize(fileSize) {
- var FileLimit = this.FileLimit;
- var isSize = fileSize / 1024 / 1024 < FileLimit.FileMaxSize; // 单位(M)
- if (!isSize) {
- this.$message.warning(
- " 文件大小不能大于" + FileLimit.FileMaxSize + FileLimit.FileUnit + "!"
- );
- return false;
- }
- return true;
- },
- // extensions 允许上传的格式
- checkExtensions(fileName, extensions) {
- var format = fileName
- .split(".")
- .pop()
- .toLowerCase(); // 用户上传的文件格式
-
- // 把允许上传文件格式的数组转为字符串
- var s = extensions.join(",");
- var exp = new RegExp(format);
- if (!exp.test(extensions)) {
- this.$message.warning("请上传 " + s + " 的格式!");
- return false;
- }
- return true;
- },
-
- // 文件上传中触发
- fileProgress(rootFile, file, chunk) {
- // 判断上传是否在上传
- if (file.isUploading()) {
- this.isUploadOk = false; // 禁止上传
- } else {
- this.isUploadOk = true; // 允许上传
- }
- },
- // 上传错误触发
- onFileError(rootFile, file, response, chunk) {
- this.$message({
- message: "上传失败,请重新上传!",
- type: "error"
- });
- },
- // 校验MD5
- computeMD5(file) {
- let fileReader = new FileReader();
- let time = new Date().getTime();
- let blobSlice =
- File.prototype.slice ||
- File.prototype.mozSlice ||
- File.prototype.webkitSlice;
- let currentChunk = 0;
- const chunkSize = 10 * 1024 * 1000;
- let chunks = Math.ceil(file.size / chunkSize);
- let spark = new SparkMD5.ArrayBuffer();
- file.pause();
-
- loadNext();
-
- fileReader.onload = e => {
- spark.append(e.target.result);
- if (currentChunk < chunks) {
- currentChunk++;
- loadNext();
- this.$nextTick(() => {});
- } else {
- let md5 = spark.end();
- this.computeMD5Success(md5, file);
- }
- };
- fileReader.onerror = function() {
- this.error(`文件${file.name}读取出错,请检查该文件`);
- file.cancel();
- };
-
- function loadNext() {
- let start = currentChunk * chunkSize;
- let end =
- start + chunkSize >= file.size ? file.size : start + chunkSize;
- fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
- }
- },
- // 验证成功
- computeMD5Success(md5, file) {
- file.uniqueIdentifier = api.randomString(32); //把md5值作为文件的识别码
- file.resume(); //开始上传
- },
- // 视频移除
- videoRemove(file, fileList) {
- this.fileListMp4 = [];
- },
- // 成功上传触发方法
- success_video: function(rootFile, file, response, chunk) {
- var response = JSON.parse(response);
- if (response.Result) {
- const fileLists = [];
- fileLists.push(response.Data);
- this.fileList = fileLists;
- } else {
- this.$message.error(response.Errstr);
- return false;
- }
- },
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。