微信小程序上传图片压缩

文章介绍了如何在微信小程序中使用canvas进行图片压缩,并实现本地下载和云存储上传的功能,详细展示了选择图片、压缩算法、尺寸调整和多图上传的过程。
摘要由CSDN通过智能技术生成

前言 

前端利用cavans实现,参考了3种常用的图片压缩方法_huangpb0624的博客-CSDN博客

压缩效果主要看你设置的最大分辨率,使用笔者的设置压缩效果可以将10多m的图压缩到400k。

代码 

wxml

<button bindtap="chooseImg">选择图片</button>
<canvas canvas-id="firstCanvas" style="width:{{ imgWidth }}px; height:{{ imgHeight }}px;"></canvas>


要隐藏canvas用这个
  <canvas style="width:{{ imgWidth }}px; height:{{ imgHeight }}px;position: absolute; top: -9999px;" canvas-id="firstCanvas"></canvas>

ts/js

实现压缩后本地下载并上传云存储

// pages/upcompress/index.ts
Page({

  /**
   * 页面的初始数据
   */
  data: {
    imgWidth: 0,
    imgHeight: 0
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad() {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  },

  chooseImg () {
    let _this = this;
    // 从本地相册选择图片或使用相机拍照
    wx.chooseImage({
        count: 1, // 最多可以选择的图片张数
        success (res) {
            const ctx = wx.createCanvasContext('firstCanvas');
            let path = res.tempFilePaths[0];
            console.log("path",path)
            wx.getImageInfo({
                src: path,
                success (res) {
                    console.log(res)

                    // 图片原始尺寸
                    let originWidth = res.width;
                    let originHeight = res.height;
                    // 最大尺寸限制,可通过设置宽高来实现图片压缩程度
                    let maxWidth = 1200,
                        maxHeight = 1600;
                    // 目标尺寸
                    let targetWidth = originWidth,
                        targetHeight = originHeight;
                    // 图片尺寸超过200x150的限制
                    if(originWidth > maxWidth || originHeight > maxHeight) {
                        if(originWidth / originHeight > maxWidth / maxHeight) {
                            // 更宽,按照宽度限定尺寸
                            targetWidth = maxWidth;
                            targetHeight = Math.round(maxWidth * (originHeight / originWidth));
                        } else {
                            targetHeight = maxHeight;
                            targetWidth = Math.round(maxHeight * (originWidth / originHeight));
                        }
                    }
                    // canvas对图片进行缩放
                    _this.setData({
                        imgWidth: targetWidth,
                        imgHeight: targetHeight
                    })

                    // 压缩图片(绘制图像到画布)
                    ctx.drawImage(path,0,0,targetWidth,targetHeight);

                    ctx.draw(false, ()=>{
                        // canvas导出为图片路径
                        wx.canvasToTempFilePath({
                            canvasId: 'firstCanvas',
                            fileType: 'jpg', //支持jpg或png
                            quality: 0.92, //图片质量
                            success(res) {
                                let compressedPath = res.tempFilePath;

                                // 使用原始文件名作为保存到系统相册的文件名
                                let fileName = path.split('/').pop();
                                
                                // 上传压缩过的图片到云存储
                                wx.cloud.uploadFile({
                                    cloudPath: 'compressed/' + fileName, // 云存储路径,包括文件名
                                    filePath: compressedPath,
                                    success: (uploadRes) => {
                                        console.log('上传成功', uploadRes.fileID);

                                        // 保存图片到系统相册
                                        wx.saveImageToPhotosAlbum({
                                            filePath: compressedPath,
                                            success () {
                                                console.log('保存到本地相册成功!')
                                            },
                                            fail () {
                                                console.log('保存到本地相册失败!')
                                            }
                                        });
                                    },
                                    fail: (error) => {
                                        console.error('上传失败', error);
                                    }
                                });
                            },
                            fail(err) {
                                console.log(err);
                            }
                        });
                    });
                }
            });
        }
    });
},


  
  
})

微调

微调适配参考,在原有基础上修改,上传图片地址前,压缩完成后返回地址并上传

async uplunbo(){
 const chooseResult = await wx.chooseImage({
          //数量限制
          count: 1,
          sourceType: ['album'],
          sizeType: ['compressed'],
          });

this.uploadlunbo(chooseResult);

},


async uploadlunbo(chooseResult){
  let that = this;
  wx.showLoading({
    title: '上传中',
  });
  const promises = chooseResult.tempFilePaths.map(async filePath => {
  // 提取每个对象的tempFilePath
  //const filePath = file.tempFilePath;//chooseMedia使用,不支持苹果
  const fileName = filePath.split('/').pop();
  const cloudPath = this.data.Path+ fileName;
  const compressedFilePath = await this.compressImage(filePath);
  console.log("filePath", filePath);// 这里压缩并返回路径
  
    return wx.cloud.uploadFile({
      cloudPath: cloudPath,
      filePath: compressedFilePath,// 这里使用压缩后的路径
      config: {
        env: this.data.envId
      }
    });
  });

  Promise.all(promises).then(results => {
    console.log('所有文件上传成功', results);
  
    results.forEach((res, index) => {
      this.setData({
        haveGetImgSrc: true,
        imgSrc: res.fileID
      });
      
      wx.cloud.callFunction({
        name: 'uploadLunbo',
        data: {
          collectionName: lunboBase,
          imgSrc: this.data.imgSrc,
          folderValue: this.data.folderValue,
          photoType: Number(this.data.op),
          position: Number(this.data.position)
        },
        success: res => {
          console.log("上传数据库成功", res);
          that.refresherpulling()
          // 执行其他操作
        },
        fail: error => {
          console.log("上传数据库失败", error);
          wx.showToast({
            title: '上传数据库失败'
          })
          // 处理错误
        }
      });
      
    });
  }).catch(e => {
    console.log(e);
    wx.hideLoading();
    wx.showToast({
      title: '上传失败'
    })
  });
  
},

多图适配

多图压缩并上传,需要自适应cavans的数量和宽高。

wxml


<button bindtap="up">选择图片</button>
<block wx:for="{{ canvasList }}" wx:for-item="item" wx:for-index="index">
    <canvas canvas-id="{{ 'canvas-' + index }}" style="width:{{ item.imgWidth }}px; height:{{ item.imgHeight }}px;position: absolute; top: -9999px;"></canvas>
  </block>

 js

Page({

data: {
    imgWidth: 0,
    imgHeight: 0,
    canvasList: [], // 初始化一个数组,用于生成 canvas
  },

async up(){
 const chooseResult = await wx.chooseImage({
          //数量限制
          count: 1,
          sourceType: ['album'],
          sizeType: ['compressed'],
          });

this.uploadColumn(chooseResult);

},


uploadColumn(chooseResult){
  let that = this;
  wx.showLoading({
    title: '上传中',
  });
  this.setData({
    countNo: 0,
    canvasList: new Array(chooseResult.tempFilePaths.length).fill({ imgWidth: 0, imgHeight: 0 }) // 初始化每个项为对象
  });
    const promises = chooseResult.tempFilePaths.map(async (filePath, index) => {
    const fileName = filePath.split('/').pop();
    const cloudPath = this.data.Path + fileName;
    const compressedFilePath = await this.compressImage(filePath, 'canvas-' + index);

    return wx.cloud.uploadFile({
      cloudPath: cloudPath,
      filePath: compressedFilePath,
      config: {
        env: this.data.envId
      }
    });
  });
  
  Promise.all(promises).then(results => {
    console.log('所有文件上传成功', results);
  
    results.forEach((res, index) => {
      this.setData({
        haveGetImgSrc: true,
        imgSrc: res.fileID
      });
      const no =  Number(this.data.no) + index
      console.log("no1", no);

      
      wx.cloud.callFunction({
        name: 'uploadColumn',
        data: {
          collectionName: this.data.columnBase,
          imgSrc: this.data.imgSrc,
          folderValue: this.data.folderValue,
          position: Number(this.data.position),
          text: this.data.describeValue,
          no: Number(this.data.no) + index,
          photoType: Number(this.data.photoTypeTmp),
        },
         
        success: function (res) {
          console.log("上传数据库成功", res);
          console.log("no2", no);
          that.data.countNo++;
          console.log("countNo",that.data.countNo);
          // that.refresherpulling()
          if(that.data.countNo==chooseResult.tempFiles.length){
            console.log("全部上传数据库成功");
            wx.hideLoading();
            //归0,貌似有时候不能,还得开头归一次
            that.setData({
              countNo: 0,
            });
            setTimeout(() => {
              //刷新
              that.refresherpulling()
            }, 100)
          }
        }
      });
      console.log("上传云存储成功", res);
    });
  
    this.setData({
      no: Number(this.data.no) + chooseResult.tempFiles.length,
    });
    console.log("chooseResult.tempFiles.length", chooseResult.tempFiles.length);
  

    
  }).catch(e => {
    console.log(e);
    wx.hideLoading();
    wx.showToast({
      title: '上传失败' + e
    })
  });
 
  
},

async compressImage(filePath, canvasId) {
  let _this = this;
  const index = Number(canvasId.split('-')[1]); // 获取canvasId中的索引

  const canvasList = _this.data.canvasList;

  return new Promise((resolve, reject) => {
    const ctx = wx.createCanvasContext(canvasId);
    
    wx.getImageInfo({
      src: filePath,
      success: res => {
        const originWidth = res.width;
        const originHeight = res.height;
        const maxWidth = 600;
        const maxHeight = 800;
        let targetWidth = originWidth;
        let targetHeight = originHeight;
        
        if (originWidth > maxWidth || originHeight > maxHeight) {
          if (originWidth / originHeight > maxWidth / maxHeight) {
            targetWidth = maxWidth;
            targetHeight = Math.round(maxWidth * (originHeight / originWidth));
          } else {
            targetHeight = maxHeight;
            targetWidth = Math.round(maxHeight * (originWidth / originHeight));
          }
        }
        // canvas对图片进行缩放

        _this.setData({
          ['canvasList[' + index + '].imgWidth']: targetWidth,
          ['canvasList[' + index + '].imgHeight']: targetHeight
        });

        
        ctx.drawImage(filePath, 0, 0, targetWidth, targetHeight);
        ctx.draw(false, () => {
          wx.canvasToTempFilePath({
            canvasId: canvasId,
            fileType: 'jpg', //支持jpg或png
            quality: 0.92, //图片质量
            success: res => {
              resolve(res.tempFilePath);
            },
            fail: err => {
              reject(err);
            }
          });
        });
      },
      fail: err => {
        reject(err);
      }
    });
  });
},



})



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值