项目实践后的图片压缩完整使用过程【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>

浙公网安备 33010602011771号