环境压缩图片"/>
uniapp在h5环境压缩图片
uniapp压缩图片的api,unipressimage在h5环境暂不支持,详见官网-平台差异说明
所以我们在这件事情上,需要超越uniapp官方。诶 听起来还不错
一、选图片
代码里面有一些vk.的操作,这是个2022年出来的云开发框架,vk的特点是让写JS的前端三天内变成全栈。有兴趣可以戳链接了解,vk的作者还坑过我一次害我22点饿着肚子在加班。vk框架秒变全栈
Q:为什么压缩(thatpressImage)和上传(that.uploadImg)都用到Promise.all()?
因为我们是支持批量上传,当选择10张图片时,我们没有理由压缩完一张再压缩下一张,JS默认是单线程执行代码。所以我们需要优化,面试时聊得最多的优化。
uploadFile() {let type = that.queryForm1.formData.type;let fileType;let extension = [];if (type === "image") {extension = ["png", "jpg", "jpeg", "gif", "bmp", "svg"];fileType = "image";} else if (type === "video") {extension = ["avi", "mp3", "mp4", "3gp", "mov", "rmvb", "rm", "flv", "mkv"];fileType = "video";} else if (type === "other") {extension = ["txt", "pdf", "xls", "xlsx", "ppt", "pptx", "doc", "docx", "rar", "zip"];}const tasksUload = [];const tasksCompress = [];uni.chooseFile({extension,success: res => {vk.showLoading("上传中...");const {tempFilePaths,tempFiles} = restempFiles.forEach((file, index) => {console.log(`图片大小:${file.size}====图片名称:${file.name}====类型${file.type}`)const filePath = tempFilePaths[index]// 图片大于1MB进行压缩if (fileType == 'image' && file.size / 1024 > 1025) {tasksCompress.push(thatpressImage(file))} else {tasksUload.push(that.uploadImg(file, fileType))}})if (tasksCompress.length > 0) {Promise.all(tasksCompress).then(files => {// 压缩完毕,拿到压缩后的图片文件数组filesfiles.forEach(file => tasksUload.push(that.uploadImg(file, fileType)))uploadFu()})} else {uploadFu()}}});function uploadFu() {Promise.all(tasksUload).then(res1 => {vk.hideLoading();that.getList();// 自己的查询接口}).catch(err => {vk.hideLoading();console.error(err);});}
},
二、压缩图片
以下是传统前端压缩思路(应该还有更高级的,可我不会,希望有大佬来评论区分享下)
uni.getImageInfo得到图片的信息
把图片画到cavans上,这一步图片已经被压缩
使用cavans的toDataURL方法得到base64文件流的格式
因为后端懒得处理base64二进制,所以我们前端要把base64二进制再转成File文件格式
Q:什么是base64二进制?
它是以data:image/png;base64开头的格式,png也可能是jpg、svg等图片类型。
它是包括小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"一共64个字符的字符集。
更详细讲解
Q:为什么png图片格式不能压缩,需要转成jpge?
因为 canvas 是不支持无损的 png 压缩的。如果我们要进行压缩,那就需要转为 jpeg ,同时 png 的透明效果将会消失。
// 压缩图片
compressImage(urlData) {vk.showLoading("压缩中...");const asyncFunc = new Promise(resolve => {uni.getImageInfo({src: urlData.path,success(res) {let originWidth = res.width; //图片原始宽let originHeight = res.height; //图片原始高let img = new Image()img.src = res.pathlet canvas = document.createElement('canvas');let ctx = canvas.getContext('2d')// 目标尺寸let targetWidth = originWidth;let targetHeight = originHeight;canvas.width = targetWidthcanvas.height = targetHeight// 图片压缩ctx.drawImage(img, 0, 0, targetWidth, targetHeight)// 将png格式文件转为jepg输出,因为png图片不能用这种方式进行压缩let filetype = urlData.type === 'image/png' ? 'image/jpeg' : urlData.type// canvas对图片进行缩放 0.5是我定义的图片质量let base64 = canvas.toDataURL(filetype, 0.5);// 将base64转换为filel流let flie = that.convertBase64UrlToFile({dataURL: base64,type: urlData.type,contentName: urlData.name})console.log('压缩后', flie)resolve(flie)},fail() {uni.showModal({title: '提示',content: '图片压缩失败',showCancel: false});}})})return asyncFunc
},
三、base64二进制转成File文件格式
说实话这段代码比较底层,我是看不太懂的,可如果我们看懂了,面试时我们便是见多识广,游刃有余,天下无敌
Q:window.atob()是什么?
btoa():从二进制数据“字符串”创建一个 Base-64 编码的 ASCII 字符串(“btoa”应读作“binary to ASCII”)
atob():解码通过 Base-64 编码的字符串数据(“atob”应读作“ASCII to binary”)
// base64转成File文件格式
convertBase64UrlToFile(base64) {let urlData = base64.dataURLlet type = base64.typelet contentName = base64.contentNamelet bytes = nullif (urlData.split(',').length > 1) { //是否带前缀bytes = window.atob(urlData.split(',')[1]) // 去掉url的头,并转换为byte} else {bytes = window.atob(urlData)}// 处理异常,将ascii码小于0的转换为大于0let ab = new ArrayBuffer(bytes.length)let ia = new Uint8Array(ab)for (let i = 0; i < bytes.length; i++) {ia[i] = bytes.charCodeAt(i)}let result = new Blob([ab], {type: type,})let result1 = new File([result], contentName, {type: type})result1.path = window.URL.createObjectURL(result)return result1
},
四、请求接口上传图片
我这里是vk的api方法,大家换成自己的axios请求就好
// 上传图片到云存储
uploadImg(file, fileType) {const asyncUload = new Promise(function(resolve, reject) {vk.callFunctionUtil.uploadFile({filePath: file.path,file: file,needSave: true,fileType,category_id: that.queryForm1.formData.category_id,addSuccess: function(res) {// 等保存到数据库后才执行resolveresolve(res);}});})return asyncUload
},
更多推荐
uniapp在h5环境压缩图片
发布评论