Vue.js实现文件上传压缩优化处理技巧

vue js实现文件上传压缩优化处理

两种方法 :

  • 第1种是借助canvas的封装的文件压缩上传
  • 第2种(扩展方法)使用compressorjs第三方插件实现

下面来详细介绍两种方法:

 借助canvas的封装的文件压缩上传

封装之前,先要对canvas相关的方法有所了解 

<canvas>简单实例如下:

<canvas id="myCanvas" width="200" height="100"></canvas>

注意: 标签通常需要指定一个id属性 (或者其他), width 和 height 属性定义的画布的大小.

使用 style 属性来添加边框:

<canvas id="myCanvas" width="200" height="100"
style="border:1px solid #000000;">
</canvas>

1.新建imgUpload.js

 将base64转换为file文件

const dataURLtoFile = (dataurl, filename) => { 
 let arr = dataurl.split(',')
 let mime = arr[0].match(/:(.*?);/)[1]
 let bstr = atob(arr[1])
 let n = bstr.length
 let u8arr = new Uint8Array(n)
 while (n--) {
 u8arr[n] = bstr.charCodeAt(n)
 }
 return new File([u8arr], filename, { type: mime })
};

使用canvas的方法实现(拓展)

drawImage() 方法在画布上绘制画布。

在画布上定位图像:

context.drawImage(img,x,y);

在画布上定位图像,并规定图像的宽度和高度:剪切图像,并在画布上定位被剪切的部分:

context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

canvas的toDataURL()方法是返回一个包含图片展示的 数据URL。可以使用type 参数其类型,默认为 png 格式 

canvas.toDataURL(type, option);

option表示0到1之间的取值,选定图片的质量,默认值是0.92 

const imgZip = (file) => {
 let imgZipStatus = new Promise((resolve, reject) => {
 let canvas = document.createElement("canvas"); // 创建Canvas对象(画布)
 let context = canvas.getContext("2d");
 let img = new Image();
 img.src = file.content; // 指定图片的DataURL(图片的base64编码数据)
 var Orientation = '';
 img.onload = () => {
 // canvas.width = 400;
 // canvas.height = 300;
 canvas.width = img.width;
 canvas.height = img.height;
 context.drawImage(img, 0, 0, canvas.width, canvas.height); 
 file.content = canvas.toDataURL(file.file.type, 0.5); // 0.92为默认压缩质量
 
 let files = dataURLtoFile(file.content, file.file.name);
 resolve(files)
 }
 })
 return imgZipStatus;
};

导出方法imgZip

export {
 imgZip
}

2.全局引入封装的方法

main.js

// 引入imgUpload方法
import * as imgUpload from "./utils/imgUpload"
Vue.prototype.$imgUpload = imgUpload;

3.页面中使用

这里使用了vant ui框架,实现的头像上传,如果用原生的input file方法也是一样的使用方式

<van-uploader :after-read="afterCard" :before-read="beforeRead" accept="image/*" class="arrart"
 :max-size="10240 * 1024" @oversize="onOversize" ref="uploadFile">
 <!-- <div class="loadingWrap" v-show="personCardloading">
 <van-loading class="colorCom uploadText" color="#fff" size="24px">{{uploadText}}</van-loading>
 </div> -->
 <van-image class="iconImg" round :src="Personal.iconUrl?$baseImgUrl+Personal.iconUrl:require('../../assets/img/touciang.png')" width="64" height="64" />
 </van-uploader>

限制上传数量

通过 max-count 属性可以限制上传文件的数量,上传数量达到限制后,会自动隐藏上传区域。

禁用文件上传

通过 disabled 属性禁用文件上传。

<van-uploader disabled />

 限制上传大小图片

// 限制上传大小图片
 onOversize(file) {
 console.log(file, "file");
 this.$toast("文件大小不能超过 10M");
 },

上传之前的图片验证 

// 上传之前的图片验证
 beforeRead(file) {
 console.log(file, "file,123");
 if (this.$utils.isImage(file.name)) {
 return true;
 } else {
 this.$toast("请上传图片格式");
 }
 },

afterCard方法,当提交了头像,先进行压缩处理,再去把formData文件流 作为参数调用接口,

获取到后台返回的图片路径,再调用更新头像接口,把获取的数据赋值显示头像的img.

// 头像上传
 afterCard(file) {
 this.$imgUpload.imgZip(file).then(resData => {
 const formData = new FormData();
 formData.append("file", resData);
 // 请求接口上传图片到服务器
 uploadImg(formData).then(res => {
 console.log(res, "图片上传");
 if (res.code == 200) {
 console.log(res.data,"res.data")
 let params = {
 bbsIconUrl: res.data,
 userId: this.id
 };
 compileUserInfo(params)
 .then(resImg => {
 console.log(resImg, "resImg");
 if (resImg.code == 200) {
 this.Personal.iconUrl =res.data;
 
 this.$toast("头像修改成功");
 } else {
 this.$toast(resImg.msg);
 }
 })
 .catch(error => {});
 } else {
 this.$toast(res.msg);
 }
 });
 });
 },

 如果这里使用原生的input file,可按照如下操作

示例:

<input type="file" id="file" accept="image/*">
import axios from 'axios';
 
document.getElementById('file').addEventListener('change', (e) => {
 const file = e.target.files[0];
 
 if (!file) {
 return;
 }
 this.$imgUpload.imgZip(file).then(resData => {
 const formData = new FormData();
 formData.append("file", resData);
 
 //接口调用
 axios.post('/upload', formData).then((res) => {
 console.log('Upload success');
 });
 })
 
});

 使用compressorjs第三方插件实现

compressorjs 是一个开源的图片处理库,提供了图片压缩、图片旋转等能力

语法:

new Compressor(file[, options])

1.compressorjs安装

npm install compressorjs --save

2.方法封装

ImageCompressor.js

quality:quality || 0.6, //压缩质量,图片压缩比 0-1

import Compressor from 'compressorjs';
export default function ImageCompressor(file, backType, quality) {
 return new Promise((resolve, reject) => {
 new Compressor(file, {
	quality:quality || 0.6, //压缩质量
	success(result) {
 if (!backType || backType == 'blob') {
 resolve(result)
 } else if (backType == 'file') {
 resolve(file)
 } else {
 resolve(file)
 }
	// resolve(result);
	},
	error(err) {
 console.log("图片压缩失败");
	reject(err);
	}
	})
 })
}

 此插件还能解决ios移动端拍照图片翻转90度问题

3.页面使用

import ImageCompressor from '@/utils/ImageCompressor'

4.头像上传处理

这里记得使用 async await,注意使用的file取值,与第一种的方法有所不同

// 头像上传
 async afterCard(file) {
 let newFile = await ImageCompressor(file.file, 'file', 0.6); //图片压缩
 const formData = new FormData();
 formData.append("file", newFile);
 uploadImg(formData).then(res => {
 if (res.code == 200) {
 this.centerInfo.iconUrl = res.data;
 let params = {
 iconUrl: res.data,
 id: this.id,
 loginType: this.loginType
 };
 updateMineIconUrl(params)
 .then(resImg => {
 console.log(resImg, "resImg");
 if (resImg.code == 200) {
 
 this.$toast("头像修改成功");
 } else {
 this.$toast(res.msg);
 }
 })
 .catch(error => {});
 } else {
 this.$toast(res.msg);
 }
 });
 
 },

如果这里使用原生的input file,可按照如下操作

示例:

<input type="file" id="file" accept="image/*">
import axios from 'axios';
import Compressor from 'compressorjs';
 
document.getElementById('file').addEventListener('change', (e) => {
 const file = e.target.files[0];
 
 if (!file) {
 return;
 }
 
 new Compressor(file, {
 quality: 0.6,
 
 success(result) {
 const formData = new FormData();
 
 formData.append('file', result, result.name);
 //接口调用
 axios.post('/upload', formData).then(() => {
 console.log('Upload success');
 });
 },
 error(err) {
 console.log(err.message);
 },
 });
 
});
作者:船长在船上原文地址:https://blog.csdn.net/SmartJunTao/article/details/128050111

%s 个评论

要回复文章请先登录注册