项目实践后的图片压缩完整使用过程【vue3+js】
van-uploader + 图片压缩 + 图片base64转成file
compressImage.js
const ACCEPT = ['image/jpg', 'image/png', 'image/jpeg'] const MAXSIZE = 1024 * 1024 * 2; const MAXTIP = "4" // 压缩算法函数 /* 1.首先拿到了base64的图片字符串 2.创建一个image对象,获得原始图片的宽度和高度 3.对原始图片的宽度和高度进行压缩达到符合条件(第一次压缩-从尺寸压缩) 4.调用canvasAPI进行绘制新的图片 5.绘制成功之后调用canvasAPI进行绘制(canvasAPI支持压缩-二次压缩-从质量压缩) 6.得到压缩后的base64 */ function compress(base64Image, file, callback) { let maxW = 1024; let maxH = 1024; const image = new Image() // 创建image对象 相当于创建a标签 image.addEventListener('load', function (e) { // image加载完成后就会触发 也就是src加载后 let radio; // 压缩比例 let needCompress = false; // 是否需要压缩 if (file.file.size > MAXSIZE) { needCompress = true; // 获得压缩宽高过后的大小(保证等比例缩放) radio = image.naturalWidth / maxW maxH = image.naturalHeight / radio } // 不需要压缩 if (!needCompress) { maxW = image.naturalWidth; maxH = image.naturalHeight; } // 第一次压缩完成 // 接下来使用canvas进行质量压缩 const canvas = document.createElement('canvas') canvas.height = maxH; canvas.width = maxW; canvas.setAttribute("id", "_compress_") // visibility hidden 需要创建的canvas隐藏 而不是不渲染DOM canvas.style.visibility = 'hidden' document.body.appendChild(canvas) const ctx = canvas.getContext('2d') ctx.clearRect(0, 0, maxW, maxH) ctx.drawImage(image, 0, 0, maxW, maxH) // 接来下就是压缩canvas 通过API将canvas输出成base64格式 const compressImage = canvas.toDataURL('image/jpeg', 0.8) // 通常压缩是0.8-0.9 callback && callback(compressImage); // 压缩完成进行后台传输逻辑 canvas.remove() }) image.src = base64Image; // document.body.appendChild(image) // 挂载 } function imgbase64Tofile(base64, fileName) { // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 let data = base64.split(','); // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) let type = data[0].match(/:(.*?);/)[1]; // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) let suffix = type.split('/')[1]; // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 const bstr = window.atob(data[1]); // 获取解码结果字符串的长度 let n = bstr.length // 根据解码结果字符串的长度创建一个等长的整形数字数组 // 但在创建时 所有元素初始值都为 0 const u8arr = new Uint8Array(n) // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 while (n--) { // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 u8arr[n] = bstr.charCodeAt(n) } // 利用构造函数创建File文件对象 // new File(bits, name, options) const time = (new Date()).valueOf() const file = new File([u8arr], `${fileName}${time}.${suffix}`, { type: type }) // 将File文件对象返回给方法的调用者 return file; } export default { compress, imgbase64Tofile }
main.js
import compressImage from './utils/compressImage'; app.config.globalProperties.$compressImage = compressImage;
上传页面
<van-uploader :before-read="beforeRead" :after-read="afterRead1" :before-delete="beforeDelete1" accept="image/*" :max-count="1" v-model="fileList1" :max-size="maxSize" image-fit="contain" @oversize="onOversize" > <div class="img_box upload_box1"></div> </van-uploader> <script setup>
import { ref, reactive,getCurrentInstance} from 'vue'
const { proxy } = getCurrentInstance()
const fileList1 = ref([]); const maxSize = ref(1024 *1024 * 4) const beforeRead = (file)=> {// 上传身份证图片前的图片格式校验 if (file.type !== 'image/jpeg' && file.type !== 'imagepng' && file.type !== 'image/jpg') { Toast.fail('请上传jpg或jpeg或png的格式图片'); return false; } else { return true; } } const afterRead1 = (file)=> { // 调用身份证图文识别接口 proxy.$compressImage.compress(file.content,file,(base64)=>{ proxy.$compressImage.imgbase64Tofile(base64,'idcardfront') }) } const onOversize = (file) => {//上传图片过大提示 Toast('文件大小不能超过4M'); }; // 删除上传的文件 const beforeDelete1= (file)=>{ fileList1.value = [] delete idcardMsg.ID_Cardname delete idcardMsg.ID_Idno } </script>