效果:
上传前:
上传后:
压缩效果一览:
代码:
这个文件封装的是图片压缩方法:取名api.js
//base64转码(压缩完成后的图片为base64编码,这个方法可以将base64编码转回file文件)
function dataURLtoFile(dataurl, name) {var arr = dataurl.split(','),mime = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]),n = bstr.length,u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new File([u8arr], name.split(".")[0] + ".png", { type: mime });}
//压缩图片
function compressImg(file) {var src;var files;var fileSize = parseFloat(parseInt(file['size']) / 1024 / 1024).toFixed(2);var read = new FileReader();read.readAsDataURL(file);return new Promise(function (resolve, reject) {read.onload = function (e) {var img = new Image();img.src = e.target.result;img.onload = function () {//默认按比例压缩var w = this.width,h = this.height;//生成canvasvar canvas = document.createElement('canvas');var ctx = canvas.getContext('2d');var base64;// 创建属性节点canvas.setAttribute("width", w);canvas.setAttribute("height", h);ctx.drawImage(this, 0, 0, w, h);if (fileSize < 1) {//如果图片小于一兆 那么不执行压缩操作base64 = canvas.toDataURL(file['type'], 1);} else if (fileSize > 1 && fileSize < 2) {//如果图片大于1M并且小于2M 那么压缩0.5base64 = canvas.toDataURL(file['type'], 0.5);} else {//如果图片超过2m 那么压缩0.2base64 = canvas.toDataURL(file['type'], 0.2);}// 回调函数返回file的值(将base64编码转成file)files = dataURLtoFile(base64, file.name); //如果后台接收类型为base64的话这一步可以省略resolve(files)};};})
};
//结尾处将该方法暴露出来供外部调用
export default {compressImg,
}
将上面图片压缩的文件放到main.js文件中引入,这样可以作为全局的方法,在任何地方使用
import api from '@/provider/common/util/api' //这里注意自己的路径Vue.prototype.$api = api //注册为全局变量
template模板中:(accept一样要设置成"image/*",才可以拉起相机和相册)
<!-- 宠物头像 --><van-field is-link @click='picInput()'><template #label><span class="color-666666">宠物靓照</span></template><template #input><div class="flex"><img:src="faceImg"alt=""class="wd-32 ht-32 img-style"/><input@change="xmTanUploadImg"id="uploadFile"type="file"accept="image/*"mutiple="mutiple"ref="uploadFile"class="file-upload"/></div></template></van-field>
样式两行:
<style lang="scss" scoped>
.img-style {border-radius: 50%;
}
.file-upload {display: none;
}</style>
vue实例中:
export default {data() {return {//这里展示一张默认图片faceImg: `${location.origin}/tkpage/T20210801751/static/dog.png`,id: '', //当前上传图片的idfileData: {}}},methods: {//触发input的点击事件picInput() {this.$refs.uploadFile.click();},async xmTanUploadImg(el) {this.id = '';var fileData = el.target.files[0];//限制上传图片大小,不能超过10mvar fileSize = fileData.size / 1024 / 1024;if ( fileSize > 10) {return this.$toast({message: '图片大小不能超过10M!'})}//this.$api.compressImg是封装的全局图片压缩方法var f = await this.$api.compressImg(fileData);console.log(fileData,'图片压缩之前fileData');console.log(f,'图片压缩之后 fffff');//FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式//并且可以轻松的将数据通过XMLHttpRequest.send() 方法发送出去//本接口和此方法都相当简单直接//如果送出时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。let formData = new FormData();formData.append("file", f);try {//以下是网络请求部分,没什么参考意义: uploadPicture 封装好的图片上传接口名字let res = await uploadPicture({timeout: 1000 * 60 * 100,headers: {"Content-Type": "multipart/form-data",Accept: "*/*",},data: formData,method: "post",});if (res.responseCode !== "000_000_000") {return this.$toast({message: res.responseMsg,});}//这里让后端老师返回了两个参数,一个是图片id,一个是图片urlthis.id = res.responseData.id// 接口回传地址,放到页面上展示this.faceImg = `${location.origin}/hopen/`+ res.responseData.url } catch (error) {return this.$toast({message: "图片上传失败,281",});} }}
}
上面是接口返回图片地址进行展示。如下代码是在本地预览图片,可适用于图片大小不超过5M的情况下:(本地预览的优点:速度快)
var fileData = el.target.files[0];// 图片大小不能超过10mvar fileSize = fileData.size / 1024 / 1024if ( fileSize > 10) {return this.$toast({message: '图片大小不能超过10M!'})}var that = this;//创建用来读取此文件的对象var reader = new FileReader();//使用该对象读取file文件reader.readAsDataURL(fileData);//读取文件成功后执行的方法函数reader.onload = function (e) {//读取成功后返回的一个参数e,整个的一个进度事件//选择所要显示图片的img,要赋值给img的src就是e中target下result里面//的base64编码格式的地址that.faceImg = e.target.result;};//下面就是压缩图片的代码了
开始做的是本地预览,上传过大图片会报错。报错原因:localStorage中最大可存5M内容,而要在本地预览的图片一旦超过5M,就会报这个错。
而我项目中,最大可上传10M图片,所以让后端返回图片链接,在页面上进行展示。
以下是控制台报错提示:
Uncaught DOMException: Failed to execute ‘setItem’ on ‘Storage’: Setting the value of ‘vuex’ exceeded the quota.