uniapp压缩图片

这篇博客分享了在uniapp中遇到图片过大导致服务器崩溃的问题,由于uni.compressImage不支持H5,作者选择了使用canvas进行图片压缩。在beforeImageUpload钩子中实现了图片压缩,通过读取文件,创建canvas并根据图片大小调整压缩比例,然后将base64编码转换回file文件进行上传。在handleSuccess方法中,可以看到压缩后的图片已成功上传。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上传图片前要进行压缩,因为图片过大,服务器会崩。
在uniapp中有uni.compressImage()压缩图片方法
但是用了这个方法报错:compressImage is not yet implemented
原因很简单,不支持h5,心态炸裂,只好换种方法了,试好好会把好用的方法发布出来的。

在这里插入图片描述

通过canvas可以压缩,和参考的不同的是只需要beforeImageUpload就行了。
代码如下:

 <el-upload list-type="picture-card" :action="action" :show-file-list="false"
	  :on-success="handleSucess"  :before-upload="beforeImageUpload">
	  <img v-if="imageUrl" :src="imageUrl" class="avatar"  width="148" height="148"/>
	  <i v-else class="el-icon-plus avatar-uploader-icon" />
  </el-upload>

js代码如下:

beforeImageUpload (file, fileList) {
   return new Promise(async (resolve, reject) => {
     if (!file.type.includes('image')) {
       this.$message.warning('请上传图片')
       reject(new Error('请上传图片'))
       return
     }
     this.isShowSpinning = true//上传之前弹框-或者成功函数中打开裁剪图片弹框
     const newFile = await this.compressImg(file)
     console.log(newFile.size,newFile,'压缩后图片大小---------------')
     resolve(newFile)
   })
 },
 // 图片压缩函数
 compressImg (file) {
   const that = this
   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
         var h = this.height
         // 生成canvas
         var 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) {
           // 如果图片小于一兆 那么压缩0.5
           base64 = canvas.toDataURL(file['type'], 0.5)
         } else if (fileSize > 1 && fileSize < 2) {
           // 如果图片大于1M并且小于2M 那么压缩0.5
           base64 = canvas.toDataURL(file['type'], 0.5)
         } else {
           // 如果图片超过2m 那么压缩0.2
           base64 = canvas.toDataURL(file['type'], 0.2)
         }
         // 回调函数返回file的值(将base64编码转成file)
         files = that.dataURLtoFile(base64, file.name) // 如果后台接收类型为base64的话这一步可以省略
         resolve(files)
       }
     }
   })
 },
  // base64转码(压缩完成后的图片为base64编码,这个方法可以将base64编码转回file文件)
  dataURLtoFile (dataurl, filename) {
    var arr = dataurl.split(',')
    var mime = arr[0].match(/:(.*?);/)[1]
    var bstr = atob(arr[1])
    var n = bstr.length
    var u8arr = new Uint8Array(n)
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr], filename, { type: mime })
  },

 handleSucess(res, file) {//这里上传已是走完:beforeImageUpload函数压缩后的图片
     console.log(file.size,file,'这里打印还是压缩之前的大小----');
     this.$nextTick(() => {//取dom更新之后的值
       this.option.img = URL.createObjectURL(file.raw);
       // this.option.img = URL.createObjectURL(this.newFile);//取到的值已是压缩后的图片,不需要从beforeImageUpload重新赋值给一个字段
       console.log(this.option.img,'打印出来的地址在浏览器下载看大小:是压缩之前的图片,但是上传成功后---后台返回url浏览器下载看大小-已经是压缩后的了,证明成功了-----------------')
     })
 },

方法2:手码压缩 和 compressorjs 压缩图片插件,
(自己参考:mobile2/pages/touristCard/myCard/faceApprove.vue)

npm install compressorjs --save

首先页面中引入:

import Compressor from 'compressorjs';

简单示例:

//场景uniapp写的h5。 图片压缩 res.tempFiles[0]是图片的Blod流
uni.chooseImage({
	count: 1,
	success: (chooseImageRes) => {
	//const tempFilePaths = chooseImageRes.tempFilePaths;//不需要压缩接口直接取值
	const tempFile = chooseImageRes.tempFiles[0];
	if (tempFile.size > 1048576) {  // 1MB = 1048576字节 
		new Compressor(tempFile, {
		  quality: 0.7, // 压缩质量
		  convertSize:false,
		  success: (result) => {
		    //url :接口传参为blob文件时:blob:http://192.168.3.141:8080/321c5ea6-7167-440e-9082-9a972660534a
		    const url = URL.createObjectURL(result);
		    //这里是Bold流转化为新的File
		    const fileA = new File([result], result.name, { type: result.type })
		    //这里取值,压缩后的处理
		  },
		  error: (error) => {
		    console.error('图片压缩失败', error);
		  },
		});
	} else {
    	console.log('图片大小合适,进行上传:', tempFilePaths[0]);
    }

  }
}) 

完整示例

//1.自己封装压缩图片方法
compressImage(file, maxWidthOrHeight, quality = 0.8) {
  return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = function (e) {
          const img = new Image();
          img.src = e.target.result;
          img.onload = function () {
              let canvas = document.createElement('canvas');
              let ctx = canvas.getContext('2d');
              // 计算等比例缩放后的尺寸
              let width = img.width;
              let height = img.height;
              if (width > height) {
                  if (width > maxWidthOrHeight) {
                      height *= maxWidthOrHeight / width;
                      width = maxWidthOrHeight;
                  }
              } else {
                  if (height > maxWidthOrHeight) {
                      width *= maxWidthOrHeight / height;
                      height = maxWidthOrHeight;
                  }
              }
              // 设置canvas尺寸
              canvas.width = width;
              canvas.height = height;
              // 绘制图片到canvas
              ctx.drawImage(img, 0, 0, width, height);
              // 将canvas内容转换为base64编码的图片
              canvas.toBlob(function (blob) {
                  // 检查图片大小,如果仍然大于1M,则继续降低质量进行压缩
                  if (blob.size > 1048576) {
                      this.compressImage(file, maxWidthOrHeight, quality - 0.1).then(resolve).catch(reject);
                  } else {
                      // 创建一个新的File对象,用于后续上传
                      const newFile = new File([blob], file.name, {
                          type: file.type,
                          lastModified: Date.now()
                      });
                      // // 创建一个URL对象,用于显示或者调试
                      const url = URL.createObjectURL(blob);
                      resolve({ file: newFile, url: url });
                  }
              },file.type, quality);
          };
      };
      reader.onerror = function (error) {
          reject(error);
      };
  });
},
//<view class="btn" @click="upLoadImg()">上传照片</view>
//上传照片点击事件
upLoadImg() {
   uni.chooseImage({
   	count: 1,
   	success: (chooseImageRes) => {
   		const tempFilePaths = chooseImageRes.tempFilePaths;
          const tempFile = chooseImageRes.tempFiles[0];
           console.log(tempFile,'原图片----')
          // 方法1
           // let lastFile = '';
           // if (tempFile.size > 1048576) {// 1MB = 1048576字节
           //       // 读取文件并进行压缩
           //       const compressFilePromise = this.compressImage(tempFile, 800); // 假设最大宽度或高度为800
           //       compressFilePromise.then((compressedFile) => {
           //            lastFile = compressedFile.url
           //            console.log('压缩后的图片:', lastFile,compressedFile);
           //            this.uploadFile(lastFile);
           //       }).catch((error) => {
           //           console.error('图片压缩失败:', error);
           //       });
           // } else {//不压缩
           //     this.uploadFile(tempFilePaths[0]);
           // }
          // 方法2插件
          let lastFile = '';
          if (tempFile.size > 1048576) {  // 1MB = 1048576字节 
              new Compressor(tempFile, {
                quality: 0.6,
                convertSize:false,
                success: (result) => {
                      //这里是Bold流转化为新的File
                      const url = URL.createObjectURL(result);
                      lastFile = new File([result], result.name, { type: result.type })
                      console.log('压缩后的图片:',result,url);
                      this.uploadFile(url);
                },
                error: (error) => {
                  console.error('图片压缩失败', error);
                },
              }); 
          } else {
              this.uploadFile(tempFilePaths[0]);
          }
   	}
   })  
},
//上传接口
uploadFile(val){
  let _this = this;
  let file = null;
  let UploadUrl = ''
 uni.uploadFile({
     url: UploadUrl,
     filePath: val,//传参blob
     name: 'file',
     formData: {
          timestamp:new Date().getTime(),//当前时间
          token:'',
     },
     success: (uploadFileRes) => {
         uni.hideLoading();
         let newData = uploadFileRes.data.replace(/[\\]/g, '')
         let imgData = JSON.parse(newData)
          //上传失败处理
         if(imgData.errno!=0 || !imgData.data){
              let decodedStr = this.decodeUnicode(imgData.message)
              uni.showToast({
                 icon: 'none',
                 title:decodedStr
              })
         }else{//上传图片接口成功-走上传人脸接口
              
         }
     }
 });    
},

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值