Vue2 | Vant uploader实现上传文件和图片

需求:

实现图片和文件的上传,单个图片超过1M则压缩,全部文件加起来不得超过10M。

效果:

1. html

<van-form ref="form"><van-field name="uploader" label="佐证材料" required><template #input><van-uploaderv-model="files"multipleaccept="":before-read="beforeRead":after-read="afterRead"@delete="deleteImg"/></template></van-field>
</van-form>

2. js:

    data() {return {files: [],fileList: [], // 已上传的图片fileIds: [], // 佐证材料文件id,上传成功之后返回的数据uploadfile: {type: '',name: ''}, // 上传单图的情况uploadfiles: [], // 上传多图的情况}},methods: {// 文件读取前触发beforeRead(e) {if (e.size > 10 * 1024 * 1024) {this.$toast.fail('文件大小不能超过10M')return false}return true},// 文件读取完成后触发afterRead(file) {if (file.length > 0) {// 多个上传file.map((item, index) => {this.uploadfiles.push({name: item.file.name,type: item.file.type})this.files[index].status = 'uploading'this.files[index].message = '上传中...'this.imgPreview(file[index].file, index)})} else {// 单个上传this.uploadfile.name = file.file.name // 获取文件名this.uploadfile.type = file.file.type // 获取类型this.files[this.files.length - 1].status = 'uploading'this.files[this.files.length - 1].message = '上传中...'// console.log('绑定的文件', this.files)this.imgPreview(file.file)}},// 删除文件deleteImg(file) {// 匹配fileList的项的fileName,相同的话把filesId对应删除this.fileList.map((item, index) => {if (item.file.name == file.file.name) {this.fileList.splice(index, 1)this.fileIds.splice(index, 1)}})},// 处理文件async imgPreview(file, index) {const self = this// 看支持不支持FileReaderif (!file || !window.FileReader) returnif (/^image/.test(file.type)) {// 创建一个readerconst reader = new FileReader()// 将图片转成 base64 格式reader.readAsDataURL(file)// 读取成功后的回调reader.onloadend = function () {const result = this.resultconst img = new Image()img.src = result// 判断图片是否小于1M,是就直接上传,反之压缩图片if (this.result.length <= 1024 * 1024) {// 上传图片self.postImg(this.result, index)} else {img.onload = function () {const data = self.compress(img)// 上传图片self.postImg(data, index)}}}} else {// 其他格式的文件const formData = new window.FormData()formData.append('file', file)// 计算现在所有图片的大小,如果加上该文件超过10M则不可上传let totalSize = 0this.fileList.map(item => {totalSize += Number(item.file.size)})let size = totalSize + file.sizeif (size > 10 * 1024 * 1024) {this.$toast.fail('当前上传附件超过最大内存10M!')return}const res = await businessUpload(formData)if (res.code === 200) {this.$toast.success('文件已上传')this.fileIds.push(res.fileId)this.fileList.push({id: res.fileId,file: file})if (index == undefined) {this.files[this.files.length - 1].status = 'done'this.files[this.files.length - 1].message = '上传成功'} else {this.files[index].status = 'done'this.files[index].message = '上传成功'}} else {this.$toast.fail('文件上传失败')if (index == undefined) {this.files[this.files.length - 1].status = 'failed'this.files[this.files.length - 1].message = '上传失败'} else {this.files[index].status = 'failed'this.files[index].message = '上传失败'}}}},// 压缩图片compress(img, Orientation) {const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')// 瓦片canvasconst tCanvas = document.createElement('canvas')const tctx = tCanvas.getContext('2d')// let initSize = img.src.length;let width = img.widthlet height = img.height// 如果图片大于四百万像素,计算压缩比并将大小压至400万以下let ratioif ((ratio = (width * height) / 4000000) > 1) {// console.log("大于400万像素");ratio = Math.sqrt(ratio)width /= ratioheight /= ratio} else {ratio = 1}canvas.width = widthcanvas.height = height// 铺底色ctx.fillStyle = '#fff'ctx.fillRect(0, 0, canvas.width, canvas.height)// 如果图片像素大于100万则使用瓦片绘制let countif ((count = (width * height) / 1000000) > 1) {// console.log("超过100W像素");count = ~~(Math.sqrt(count) + 1) // 计算要分成多少块瓦片// 计算每块瓦片的宽和高const nw = ~~(width / count)const nh = ~~(height / count)tCanvas.width = nwtCanvas.height = nhfor (let i = 0; i < count; i++) {for (let j = 0; j < count; j++) {tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh)ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)}}} else {ctx.drawImage(img, 0, 0, width, height)}// 进行最小压缩const ndata = canvas.toDataURL('image/jpeg', 0.4)tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0return ndata},// 提交图片到后端async postImg(base64, index) {const file = this.dataURLtoFile(base64, index)const formData = new window.FormData()formData.append('file', file)// 计算现在所有图片的大小,如果加上该文件超过10M则不可上传let totalSize = 0this.fileList.map(item => {totalSize += Number(item.file.size)})let size = totalSize + file.sizeif (size > 10 * 1024 * 1024) {this.$toast.fail('当前上传附件超过最大内存10M!')return}const res = await businessUpload(formData)if (res.code === 200) {this.$toast.success('图片已上传')this.fileIds.push(res.fileId)this.fileList.push({id: res.fileId,file: file})if (index == undefined) {this.files[this.files.length - 1].status = 'done'this.files[this.files.length - 1].message = '上传成功'} else {this.files[index].status = 'done'this.files[index].message = '上传成功'}} else {this.$toast.fail('图片上传失败')if (index == undefined) {this.files[this.files.length - 1].status = 'failed'this.files[this.files.length - 1].message = '上传失败'} else {this.files[index].status = 'failed'this.files[index].message = '上传失败'}}},// 将base64转换为文件dataURLtoFile(dataurl, index) {var arr = dataurl.split(',')var bstr = atob(arr[1])var n = bstr.lengthvar u8arr = new Uint8Array(n)while (n--) {u8arr[n] = bstr.charCodeAt(n)}if (index == undefined) {// 单图上传return new File([u8arr], this.uploadfile.name, {type: this.uploadfile.type})} else {// 多图上传return new File([u8arr], this.uploadfiles[index].name, {type: this.uploadfiles[index].type})}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/108516.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小红书直播人物专访:GMV破千万策略心得

采访手记&#xff1a;2023年来&#xff0c;小红书电商动作频频&#xff0c;直播带货已然成为品牌营销的重要场域。面对竞争压力的骤然增加&#xff0c;如何适应当下的游戏规则、释放更大的商业潜力&#xff0c;成为多数品牌入局后亟待解决的难点。 为此&#xff0c;千瓜特约采…

TypeScript枚举(Enums)和泛型(Generics)

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 枚举 异构枚举 枚举成员的类型 泛型 1. 函数泛型 2. 接口泛型 3. 类泛型 接下来我们将学习TypeScript 中的两…

SuperMap iClient3D 11i (2023) SP1 for Cesium之移动实体对象

作者&#xff1a;nannan 目录 前言 一、代码思路 1.1 绘制面实体对象 1.2 鼠标左键按下事件 1.3 鼠标移动事件 1.4 鼠标左键抬起事件 二、运行效果 三、注意事项 前言 SuperMap 官网三维前端范例 编辑线面&#xff0c;可以对面实体对象的节点进行增加、删除以及修改位置…

部署笔记:文件句柄调整和磁盘分区 02

系统默认是1024&#xff0c;基本不够&#xff0c;会报“too many open files”的错误。因此需要调整。 系统文件句柄数调整 # 编辑打开文件&#xff0c;在文末追加两行配置 vim /etc/security/limits.conf # 需要添加的配置&#xff0c;注意别漏了前面的*号 # * 指所有用户、…

linux 下 C++ 与三菱PLC 通过MC Qna3E 二进制 协议进行交互

西门子plc 有snap7库 进行交互&#xff0c;并且支持c 而且跨平台。但是三菱系列PLC并没有现成的开源项目&#xff0c;没办法只能自己拼接&#xff0c;我这里实现了MC 协议 Qna3E 帧&#xff0c;并使用二进制进行交互。 #pragma once#include <stdio.h> #include <std…

第21章_瑞萨MCU零基础入门系列教程之事件链接控制器ELC

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

TableConvert-免费在线表格转工具 让表格转换变得更容易

在线表格转工具TableConvert TableConvert 是一个基于web的免费且强大在线表格转换工具&#xff0c;它可以在 Excel、CSV、LaTeX 表格、HTML、JSON 数组、insert SQL、Markdown 表格 和 MediaWiki 表格等之间进行互相转换&#xff0c;也可以通过在线表格编辑器轻松的创建和生成…

A股风格因子看板 (2023.09 第03期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格暴露等。 今日为该因子跟踪第03期&#xff0c;指数组合数据截止日2023-08-31&#xff0c;要点如下 近1年A股风格因子检验统…

第四范式通过聆讯,AI上市公司将再添薪火

四次递表之后&#xff0c;估值超过200亿元的AI独角兽第四范式近日如愿通过港交所聆讯&#xff0c;即将成为资本市场AI皇冠上的又一颗明珠。 第四范式成立于2014年&#xff0c;历经11轮融资&#xff0c;不仅股东阵容豪华&#xff0c;也在商业化层面进展可观。今年4月底&#xf…

华为云云耀云服务器L实例评测|老用户回归的初印象

华为云云耀云服务器L实例评测&#xff5c;老用户回归的初印象 前言一、新面孔1. 云耀云服务器2. 服务器特色 二、上手感官体验1. 性价比感受2. 推荐宝塔面板3. CloudShell登录4. 安全性 总结 前言 其实笔者接触华为云已经很久了&#xff0c;第一次使用的云服务器就是华为云。当…

【计算机网络】什么是WebSocket?

目录 WebSocket简介协议优点使用场景 WebSocket WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信&#xff0c;位于OSI模型的应用层。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务器主动向客户端推送数据。在WebSocket API中&a…

电脑死机的时候,CPU到底在做什么?

电脑死机&#xff0c;应该每个接触计算机的小伙伴都经历过吧。 尤其是早些年&#xff0c;电脑配置还没现在这么高的时候&#xff0c;多开几个重量级应用程序&#xff0c;死机就能如约而至&#xff0c;就算你把键盘上的CTRLALTDELETE按烂了&#xff0c;任务管理器也出不来&…