1. 效果图如下:
  2. 文件所在位置:
  3. view/huge_file_upload/huge_file_upload.vue:(在项目中使用?)
<template><div><div style="width: 350px"><FileUploader:config="config"@fileUploadFinished="fileUploadFinishedHandle"@fileDeleteFinished="fileDeleteFinishedHandle"ref="fileUploader1"/></div><sg-button type="primary" @click="clear">重置</sg-button></div>
</template><script>
import FileUploader from "@/components/FileUploader";
import { IFileConfig } from "@/components/FileUploader/IFileConfig";
const config = new IFileConfig();
config.domId = "file";
config.isMultiple = true;
// config.cantDeleteServerFile = true
export default {name: "HugeFileUpload",components: {FileUploader,},data() {return {config: config,};},methods: {fileUploadFinishedHandle(e) {console.log(e);},fileDeleteFinishedHandle(e) {console.log(e);},clear() {this.$refs.fileUploader1.clear();},},mounted() {},
};
</script><style lang="scss" scoped></style>
  1. components/FileUploader/api/index.js:
import request from "@/utils/axios";/*** 上传分片* @returns*/
export function fileSliceUpload(data) {return request({url: "/ami/ma01-02-056/minio-file/fileSliceUpload",method: "POST",data,});
}/*** 合并文件分片* @returns*/
export function mergeSlice(data) {return request({url: "/ami/ma01-02-056/minio-file/mergeSlice",method: "POST",data,});
}/*** 小文件上传,不分片* @returns*/
export function fileUpload(data) {return request({url: "/ami/ma01-02-056/minio-file/fileUpload",method: "POST",data,});
}/*** 删除文件* @returns*/
export function deleteFile(data) {return request({url: "/ami/ma01-02-056/minio-file/deleteFile",method: "POST",data,});
}
  1. components/FileUploader/assets/图片(图片所在位置)
  2. components/FileUploader/IFileConfig.js:(文件限制封装)
export class IFileConfig {constructor() {}// iddomId = "";// 是否多文件isMultiple = false;// 文件类型fileAccept = ".zip, .rar";// 切片长度sliceLength = 1024 * 1024 * 5; // 5M// 文件大小限制maxFileSize = 1024 * 1024 * 1024 * 5; // 5G// 禁止删除上传成功的文件cantDeleteServerFile = false
}
  1. components/FildeUploader/index.vue:(上传文件的主要逻辑)
<template><div><div class="uploader-container"><inputv-if="config.isMultiple"type="file"name="file"multiple="multiple":id="config.domId"style="display: none"@change="fileChosen":accept="config.fileAccept"/><inputv-elsetype="file"name="file":id="config.domId"style="display: none"@change="fileChosen":accept="config.fileAccept"/><imgsrc="./assets/upload.png"class="upload-img-btn"alt=""@click="openFileWindow()"v-if="uploadStatus === 'n'"/><div class="file-list" v-else><sg-row v-for="(item, index) in fileList" :key="'01_' + index" class="file-item"><sg-col :span="2"><img src="./assets/uploaded.png" style="width: 16px; height: 16px; margin-top: 13px" alt="" /></sg-col><sg-col :span="19"><div style="white-space: nowrap; text-overflow: ellipsis; overflow: hidden">{{ item.file.name }}</div></sg-col><sg-col :span="3" style="text-align: right"><span v-if="uploadStatus === 'u' || uploadStatus === 'f'">{{ item.percent }}%</span><span v-if="item.isDelServerFile">0%</span><imgsrc="./assets/del.png"style="width: 15px; height: 16px; margin: 0 auto; margin-top: 13px; cursor: pointer"alt=""@click="delFile(index, item)"v-if="(uploadStatus === 'w' || uploadStatus === 's') && !item.isDelServerFile && delImgBtnFlag"/></sg-col></sg-row></div><div style="width: 100px; margin: 0 auto"><sg-button type="primary" :loading="true" v-if="uploadStatus === 'u'">上传中</sg-button><sg-buttontype="primary"@click="uploadBtnClickHandle()":disabled="uploadStatus === 'n'"v-if="uploadStatus === 'n' || uploadStatus === 'w'">上传文件</sg-button><sg-button type="primary" @click="reUpload()" v-if="uploadStatus === 'f'">断点续传</sg-button></div><div style="text-align: center; margin-top: 20px">注:限上传3个文件,单个文件最大为{{ maxFileSize }}G</div></div></div>
</template><script>
import { fileSliceUpload, mergeSlice, fileUpload, deleteFile } from "./api";
import { deepClone } from "@/utils/util";
import { IFileConfig } from "./IFileConfig";
const uuid = () => {const temp_url = URL.createObjectURL(new Blob());const uuid = temp_url.toString(); // blob:https://xxx.com/b250d159-e1b6-4a87-9002-885d90033be3URL.revokeObjectURL(temp_url);return uuid.substr(uuid.lastIndexOf("/") + 1);
};
export default {name: "HugeFileUpload",props: {config: {type: IFileConfig,default: () => {},},},data() {return {// DOM相关fileIdForData: "",fileDom: null,fileList: [],uploadImgBtnFlag: true,maxFileSize: 5,// 删除按钮显示标志delImgBtnFlag: true,// 配置相关bytesPerPiece: this.config.sliceLength, // 每个文件切片大小定为5M// 上传相关taskList: [],sliceUrlList: {},// 文件切片列表fileSliceList: [],uploadStatus: "n", // n: 没有选择文件, w: 等待,u:正在上传,f: 任务执行完,但是有失败任务,s: 全部执行成功fileIdList: {},// 返参mergeResult: [],};},methods: {openFileWindow() {this.fileDom.click();},fileChosen() {//   console.log(e);if (this.fileDom.files && this.fileDom.files.length) {const len = this.fileDom.files.length < 4 ? this.fileDom.files.length : 3;for (let i = 0; i < len; i++) {const f = this.fileDom.files[i];if (f.size <= this.config.maxFileSize) {let blob = deepClone(this.fileDom.files[i]);// console.log(this.fileDom.files[i]);this.fileList.push({file: blob,percent: 0,filename: blob.name,isDelServerFile: false,});}}//   this.uploadImgBtnFlag = false// 变更组件状态 等待上传this.uploadStatus = "w";this.fileDom.value = "";//   console.log(this.fileDom.files);}},delFile(index, item) {if (this.uploadStatus === "w") {this.fileList.splice(index, 1);if (this.fileList.length === 0) {// this.uploadImgBtnFlag = true;// 变更组件状态 没有选择文件this.uploadStatus = "n";}} else {//   const formData = new FormData();//   formData.append("fileId", this.fileIdList[filename] * 1);this.deleteFile(this.fileIdList[item.filename] * 1, item);}},// 删除文件deleteFile(formData, fileInfo) {fileInfo.isDelServerFile = true;deleteFile(formData).then((res) => {if (res.status === 200) {this.fileList = this.fileList.filter((item) => item.filename !== fileInfo.filename);delete this.fileIdList[fileInfo.filename];if (this.fileList.length === 0) {this.uploadStatus = "n";}this.$emit("fileDeleteFinished", { fileInfo, res });} else {console.log(res);fileInfo.isDelServerFile = false;}},(err) => {console.log(err);fileInfo.isDelServerFile = false;});},mergeSlice(fileSliceList, totalPieces, filesize, filename) {return new Promise((resolve) => {// 回调计数器let count = 0;for (const item of fileSliceList) {if (item.status === "1") {count++;}}if (count == totalPieces) {console.log("merge happened");const param = {fileSize: Math.ceil(filesize / 1024),fullName: filename,sliceList: this.sliceUrlList[filename],sliceNum: totalPieces,};mergeSlice(param).then((res) => {if (res.status === 200) {// console.log(res);resolve(res);} else {resolve({type: "ErrorOrException",msg: res,});}},(err) => {// console.log(err);resolve({type: "ErrorOrException",msg: err,});});} else {resolve({type: "ErrorOrException",msg: null,});}});},fileSliceUpload(formData) {return new Promise(function (resolve) {fileSliceUpload(formData).then((res) => {if (res.status === 200) {resolve(res);} else {resolve({type: "ErrorOrException",msg: res,});}},(err) => {// reject(err)// console.log(err);resolve({type: "ErrorOrException",msg: err,});});});},// 小文件上传fileUpload(formData) {return new Promise(function (resolve) {fileUpload(formData).then((res) => {if (res.status === 200) {resolve(res);} else {resolve({type: "ErrorOrException",msg: res,});}},(err) => {// reject(err)// console.log(err);resolve({type: "ErrorOrException",msg: err,});});});},cutFileIntoPieces(blob, bytesPerPiece, totalPieces) {const uuidfolder = uuid();// 开始切割的位置let start = 0;// 切割的结束位置let end;// 切片的索引let index = 0;// 文件的大小const filesize = blob.size;// console.log(filesize);// 启动while循环对文件切片while (start < filesize) {// 设置切片的结束位置end = start + bytesPerPiece;// 对最后一片数据进行处理(可以省略)if (end > filesize) {end = filesize;}// 切割文件const chunk = blob.slice(start, end); //切割文件const sliceIndex = uuidfolder + "_" + index;// 利用formData来传递数据const formData = new FormData();formData.append("sliceFile", chunk);formData.append("sliceName", sliceIndex);formData.append("sliceNo", index);formData.append("sliceNum", totalPieces);formData.append("sliceUrl", "");this.fileSliceList.push({formData,sliceIndex,index,status: "0", // 0: 未上传或上传失败,1: 成功上传});start = end;index++;}},createTasks() {if (this.fileList && this.fileList.length) {for (const item of this.fileList) {const blob = item.file;// 文件的大小const filesize = blob.size;// console.log(filesize);// 文件的名称const filename = blob.name;if (filesize <= this.bytesPerPiece) {// 利用formData来传递数据const formData = new FormData();formData.append("multipartFile", blob);this.taskList.push({type: "small",status: "0",filename,formData,callback: this.fileUpload,});} else {//计算文件切片总数let totalPieces = Math.ceil(filesize / this.bytesPerPiece);// 清空文件切片this.fileSliceList = [];this.cutFileIntoPieces(blob, this.bytesPerPiece, totalPieces);if (this.fileSliceList && this.fileSliceList.length) {for (const slice of this.fileSliceList) {this.taskList.push({type: "slice",status: "0",slice,filename,totalPieces,// callback: this.fileSliceUpload(slice.formData),callback: this.fileSliceUpload,});}const t = [];for (const item of this.fileSliceList) {t.push({index: item.index,status: "0", // 0: 未上传或上传失败,1: 成功上传});}this.taskList.push({type: "merge",status: "0",filename,fileSliceList: t,totalPieces,filesize,// callback: this.mergeSlice(deepClone(this.fileSliceList), totalPieces, filesize, filename),callback: this.mergeSlice,});}}}}},async runTask() {const setPercent = (filename, percent) => {const file = this.fileList.filter((item) => item.filename === filename);if (file && file.length) {file[0].percent = percent;}};for (const task of this.taskList) {if (task.status === "0") {console.log(task);if (task.type === "slice") {const res = await task.callback(task.slice.formData);if (!res.type) {// 变更状态task.status = "1"; // 成功上传// task.slice.status = '1'// 更新合并任务中储存的切片列表的状态const t = this.taskList.filter((item) => item.type === "merge" && item.filename === task.filename);if (t && t.length) {const s = t[0].fileSliceList.filter((fs) => fs.index === task.slice.index);if (s && s.length) {s[0].status = "1";}}// 已经成功上传的切片const sib = this.taskList.filter((item) => item.type === "slice" && item.filename === task.filename && item.status === "1");const p = sib && sib.length ? sib.length : 0;// 变更文件上传百分比 最大 90setPercent(task.filename, parseInt((p / task.totalPieces) * 90));// const file = this.fileList.filter(item => item.filename === task.filename)// if (file && file.length) {//     file[0].percent = p / task.totalPieces * 90// }// 保存返回数据const {data: {data: { sliceUrl },},} = res;if (!this.sliceUrlList[task.filename]) {this.sliceUrlList[task.filename] = [];}this.sliceUrlList[task.filename].push({sliceFile: null,sliceName: task.slice.sliceIndex,sliceNo: task.slice.index,sliceUrl,});}} else if (task.type === "merge") {const res = await task.callback(task.fileSliceList, task.totalPieces, task.filesize, task.filename);if (!res.type) {task.status = "1";// const file = this.fileList.filter(item => item.filename === task.filename)// if (file && file.length) {//     file[0].percent = 100// }setPercent(task.filename, 100);this.fileIdList[task.filename] = res.data.fileId;this.mergeResult.push(res);}} else if (task.type === "small") {const res = await task.callback(task.formData);console.log(res);if (!res.type) {task.status = "1";setPercent(task.filename, 100);this.fileIdList[task.filename] = res.data.data.fileId;this.mergeResult.push(res);}}}}// 执行状态判断const t = this.taskList.filter((task) => task.status === "0");if (t && t.length) {// 变更组件状态 任务执行完,但是有失败任务this.uploadStatus = "f";} else {// 变更组件状态 全部执行成功this.uploadStatus = "s";this.taskList = [];this.fileSliceList = [];this.sliceUrlList = {};this.$emit("fileUploadFinished", deepClone(this.mergeResult));this.mergeResult = [];//if (this.config.cantDeleteServerFile) {this.delImgBtnFlag = false;}}},uploadBtnClickHandle() {// 变更组件状态 正在上传this.uploadStatus = "u";this.createTasks();this.runTask();},clear() {this.fileList = [];this.uploadImgBtnFlag = true;this.delImgBtnFlag = true;this.taskList = [];this.sliceUrlList = {};this.fileSliceList = [];this.mergeResult = [];this.uploadStatus = "n";},reUpload() {// 变更组件状态 正在上传this.uploadStatus = "u";// this.sliceUpload(0)this.runTask();},},created() {// this.fileIdForData = this.config.fileId// this.fileIdForData = this.config.fileId},mounted() {this.fileDom = document.getElementById(this.config.domId);// console.log(this.fileDom);this.maxFileSize = parseInt((this.config.maxFileSize * 1) / 1024 / 1024 / 1024);},watch: {// fileId(newVal) {//     if (newVal) {//         this.fileIdForData = newVal//     }// }},
};
</script><style lang="scss" scoped>
.uploader-container {border: 1px dashed #bacfe7;height: 250px;border-radius: 5px;background: #f4f7fa;.upload-img-btn {width: 80px;height: 80px;margin: 40px auto;cursor: pointer;}.file-list {height: 160px;.file-item {margin: 5px 8px;background: #fff;height: 44px;line-height: 44px;padding: 0 10px;}}
}
</style>

6.基于vue封装的上传文件等功能相关推荐

  1. html5封装图片,简单封装前端上传文件/图片

    前言 最近项目会一直用到各种类型的上传文件的功能, 所以就基于elment-ui简单的做了一个封装, 比较好用 正文 引入 import TestUpload from '../components/ ...

  2. Vue使用WebUploader上传文件/压缩包

    Vue使用WebUploader上传文件/压缩包 npm i webuploader -S 引入 //引入webuploader import WebUploader from "webup ...

  3. vue method ajax上传文件,前端上传文件追根溯源_和_antd_vue上传文件实例

    背景 平,过现前个能文使近记接的端问对字用近记接时工作中经常会遇到需要上传文件的情况,如果你用ant design 或者element ,它们都提供了上传的组件. 我们分别来看一下element 和 ...

  4. antd vue表单上传文件_Vue编译出静态文件上传七牛CDN

    Vue作为目前比较流行的前端开发框架,在前后端分离比较时尚的今天异常火热,下面分享下怎么把Vue编译出来的静态文件上传到CDN,在这里主要是七牛云的CDN. Vue项目进行编译 编译命令: npm r ...

  5. vue前端实现上传文件,vue 上传文件

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传  ...

  6. vue前端实现上传文件的两种方式

    1.使用form表单的形式 第一种方式就是使用FormData的方式进行上传 html代码: <el-form :model="upform" :rules="up ...

  7. antd vue表单上传文件_AntDesign vue学习笔记-自定义文件上传

    上传文件时实际可能需要传输一个token. 方法一: 1.查看vue antdesign文档 https://vue.ant.design/components/upload-cn/ 2.使用cust ...

  8. 基于vue+el-upload图片上传(自用屎山)

    一份屎山版的图片上传 <template><!--图片上传个数 max图片预上传列表 fileList图片上传和回显容器 upLoadListref提交图片的方法 submitHan ...

  9. vue+element-ui 实现上传文件、下载模板、批量导入、导出

    在后台管理系统的项目开发中,为了系统使用更加方便,通常页面中会有批量导入,导出,上传文件,下载模板等功能.刚好最近做的项目中,有这些功能,正好借此机会做个总结. 页面上的功能如上图所示. 1 下载模板 ...

最新文章

  1. B. 熟练剖分(tree) (概率DP)
  2. 【Android】关于Android控件EditText的属性InputType的一些经验
  3. php 邮箱验证原理
  4. mysql用户添加_MySQL用户添加
  5. Protobuf3教程
  6. php中将excel写入mysql数据库的示例
  7. server2012 AD域 radius 802.1x认证
  8. mysql from_unixtime(_MySQL 数据库中日期与时间函数 FROM_UNIXTIME(), UNIX_TIME()
  9. CAS3.5.x(x1)支持OAuth2 server
  10. html5提供类似“JQuery”中操作类名的方法
  11. mysql乘法函数_数据库入门(MySQL):mySQL运算符与mySQL常用函数
  12. 高程拟合的matlab代码,利用MATLAB结合C语言实现GPS高程二次曲面拟合
  13. postSQL hash分表
  14. 基于5片FPGA处理的PCIE光纤传输硬件加速卡
  15. java自行车怎么调档_变速的自行车如何调档
  16. 奇怪的sqlconnection.open错误
  17. ios闹钟铃声实现代码
  18. 8通道250MSPS 14位AD采集FMC子卡
  19. ecshop模板教程——类似淘宝滚屏漂浮返回
  20. java 多个线程同时写同一个文件

热门文章

  1. 目的和目标的差异|丰田自动工程完结的目的、目标、应用化的意义和明确、二
  2. 我在传智播客上课的感受
  3. 伪原创视频 审核 抖音短视频md5修改在线
  4. 中小型企业网络局域网实例-核心交换机配置
  5. Spark MLlib机器学习 Pipelines
  6. Speedoffice(PPT)如何插入艺术字体
  7. 基于OSG讲解一下LOD
  8. 使用Chrome调试微信内置浏览器
  9. 过程FMEA步骤五:风险分析
  10. win10 uwp 装机必备应用 含源代码