当前位置: 首页 > news >正文

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})}}}

相关文章:

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

需求&#xff1a; 实现图片和文件的上传&#xff0c;单个图片超过1M则压缩&#xff0c;全部文件加起来不得超过10M。 效果&#xff1a; 1. html <van-form ref"form"><van-field name"uploader" label"佐证材料" required><t…...

第二十一章 Classes

文章目录 第二十一章 ClassesClasses类名和包类定义的基本内容 第二十一章 Classes Classes 类定义并不是 ObjectScript 的正式组成部分。相反&#xff0c;可以在类定义的特定部分中使用 ObjectScript&#xff08;特别是在方法定义中&#xff0c;可以在其中使用其他实现语言&…...

Ubuntu不能上网解决办法

问题及现象 Ubuntu的虚拟机&#xff08;18.04&#xff09;总是莫名就不能上网了。 使用ifconfig -a 查看&#xff0c;ensxx&#xff08;xx为虚拟机分配的id号&#xff09;对应的网卡有mac地址&#xff0c;但是没有分配ip地址。 Network中也没有Wired的选项。 临时解决方案 使…...

百度飞浆OCR识别表格入门python实践

1. 百度飞桨&#xff08;PaddlePaddle&#xff09; 百度飞桨&#xff08;PaddlePaddle&#xff09;是百度推出的一款深度学习平台&#xff0c;旨在为开发者提供强大的深度学习框架和工具。飞桨提供了包括OCR&#xff08;光学字符识别&#xff09;在内的多种功能&#xff0c;可…...

直接插入排序、希尔排序详解。及性能比较

直接插入排序、希尔排序详解。及性能比较 一、 直接插入排序1.1 插入排序原理1.2 代码实现1.3 直接插入排序特点总结 二、希尔排序 ( 缩小增量排序 )2.1 希尔排序原理2.2 代码实现2.3 希尔排序特点总结 三、直接插入排序和希尔排序性能大比拼 !!!3.1 如何对比性能&#xff1f;准…...

2023备战秋招Java面试八股文合集

Java就业大环境仍然根基稳定&#xff0c;市场上有很多机会&#xff0c;技术好的人前景就好&#xff0c;就看你有多大本事了。小编得到了一份很不错的资源&#xff0c;建议大家可以认真地来看看以下的资料&#xff0c;来提升一下自己的核心竞争力&#xff0c;在面试中轻松应对面…...

SLAM中的二进制词袋生成过程和工作原理

长期视觉SLAM (Simultaneous Localization and Mapping)最重要的要求之一是鲁棒的位置识别。经过一段探索期后&#xff0c;当长时间未观测到的区域重新观测时&#xff0c;标准匹配算法失效。 当它们被健壮地检测到时&#xff0c;回环检测提供正确的数据关联以获得一致的地图。…...

算法训练第五十九天

503. 下一个更大元素 II - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; class Solution { public:vector<int> nextGreaterElements(vector<int>& nums) {vector<int> nums1(nums.begin(), nums.end());nums.insert(nums.end(), nums1.beg…...

二叉树oj题

目录 层序遍历(一) 题目 思路 代码 层序遍历(二) 题目 思路 代码 根据二叉树创建字符串 题目 思路 代码 二叉树的最近公共祖先 题目 思路 代码 暴力版 队列版 栈版 bs树和双向链表 题目 思路 代码 前序中序序列构建二叉树 题目 思路 代码 中序后序…...

华为数通方向HCIP-DataCom H12-831题库(单选题:1-20)

第1题 关于IPSG下列说法错误的是? A、IPSG可以防范IP地址欺骗攻击 B、IPSG是一种基于三层接口的源IP地址过滤技术 C、IPSG可以开启IP报文检查告警功能,联动网管进行告警 D、可以通过IPSG防止主机私自更改IP地址 答案: B 解析: IPSG(入侵防护系统)并不是基于三层接口的源I…...

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

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

伦敦金实时行情中的震荡

不知道各位伦敦金投资者&#xff0c;曾经花过多长的时间来观察行情走势的表现&#xff0c;不知道大家是否有统计过&#xff0c;其实行情有60%-70%的时间&#xff0c;都会处于没有明显方向的震荡行情之中呢&#xff1f;面对长期的震荡行情&#xff0c;伦敦金投资者道理应该如何应…...

蓝桥杯打卡Day7

文章目录 阶乘的末尾0整除问题 一、阶乘的末尾0IO链接 本题思路&#xff1a;由于本题需要求阶乘的末尾0&#xff0c;由于我们知道2*510可以得到一个0&#xff0c;那么我们就可以找出2的数和5的数&#xff0c;但是由于是阶乘&#xff0c;所以5的数量肯定是小于2的数量&#xf…...

Mobile Vision Transformer-based Visual Object Tracking

论文作者&#xff1a;Goutam Yelluru Gopal,Maria A. Amer 作者单位&#xff1a;Concordia University 论文链接&#xff1a;https://arxiv.org/pdf/2309.05829v1.pdf 项目链接&#xff1a;https://github.com/goutamyg/MVT 内容简介&#xff1a; 1&#xff09;方向&#…...

HTTP反爬困境

尊敬的程序员朋友们&#xff0c;大家好&#xff01;今天我要和您分享一篇关于解决反爬困境的文章。在网络爬虫的时代&#xff0c;许多网站采取了反爬措施来保护自己的数据资源。然而&#xff0c;作为程序员&#xff0c;我们有着聪明才智和技术能力&#xff0c;可以应对这些困境…...

从零开始探索C语言(九)----函数指针与回调函数

函数指针 函数指针是指向函数的指针变量。 通常我们说的指针变量是指向一个整型、字符型或数组等变量&#xff0c;而函数指针是指向函数。 函数指针可以像一般函数一样&#xff0c;用于调用函数、传递参数。 函数指针变量的声明&#xff1a; typedef int (*fun_ptr)(int,i…...

智慧工厂的基础是什么?功能有哪些?

关键词&#xff1a;智慧工厂、智慧工厂数字化、设备设施数字化、智能运维、工业互联网 1.智慧工厂的定义 智慧工厂是以数字化信息形式的工厂模型为基础&#xff0c;以实现制造系统离线分析设计和实际生产系统运行状态在线监控的新型工厂。智慧工厂的建设在于以高度集成的信息化…...

LeetCode 238. 除自身以外数组的乘积

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 使用前缀和进行解决该题&#xff0c;只不过与之前前缀和不同的是这个题目计算前缀和的时候不需要计算当前元素&#xff0c;也就是当前位置前缀和的值其实是不包含当前元素的前缀和。…...

点击劫持概念及解决办法

1.点击劫持的概念 点击劫持 (Clickjacking) 技术又称为界面伪装攻击 (UI redress attack )&#xff0c;是一种视觉上的欺骗手段。攻击者使用一个或多个透明的 iframe 覆盖在一个正常的网页上&#xff0c;然后诱使用户在该网页上进行操作&#xff0c;当用户在不知情的情况下点击…...

【Spring】手动实现Spring底层机制-问题的引出

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理手动实现Spring底层机制-问题的引出 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x1…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...