uniapp h5拍照上传照片

 前段时间公司要弄一个uniapp的H5拍照上传的功能,看这位博主 常德_威少 的博客完成,于是想把我写的和补充记录一下

首先调用uni.chooseImage(具体看官网),因为手机拍照像素尺寸很大,官方图片压缩不支持H5,于是参考了 常德_威少 的博客。

话不多说,基本思路是:

1、先将图片的file文件转成baseURL
2、创建一个image标签去接收文件获取图片的宽高和比例。
3、创建canvas画布设置画布的大小。
4、将图片绘制到canvas上面。
5、对canvas进行压缩处理,获得新的baseURL
6、将图片的baseURL转化回file格式。

最后我们调用这个方法可以拿到图片的file格式

根据接口所需要的格式再继续转换,我最后转换为blob

我们在utils写一个方法 Compress.js

import { Message } from 'element-ui'
class Compress {
  constructor(file,width = -1,quality = 0.92,targetSize = 3){
    this.file = file//文件
    this.width = width//不传初始赋值-1,等比缩放不用传高度
    this.quality = quality//不传初始赋值0.92。值范围0~1
    this.targetSize = targetSize//目标大小,控制上传图片大小 传值方式:targetSize:1 * 1024 * 1024的值默认3m
  }
  // 压缩
  compressUpload(){
    const rawImage = this.file//获取文件
    // console.log(111);
    if(!rawImage) return false
    // console.log(222);
    if(!this.isImage(rawImage)){
      // console.log(333);
      Message.error('图片只支持.jpg, .png, .bmp, .jpeg, .webp格式!')
      return false
    }
    return new Promise(async (resolve,reject) => {
      if(!this.isLimitSize(rawImage)){
        // 需压缩
        let imageFile = await this.readImage(rawImage)
        console.log('imageFile',imageFile)
        resolve({
          file:imageFile.file
        })
        console.log('压缩后上传')
      }else{
        // 无需压缩
        resolve({
          file:rawImage
        })
        console.log('原图上传')
      }
    })
  }
  /**
   * @desc 图片压缩
   * @param image 被压缩的img对象
   * @param type 压缩后转换的文件类型
   **/
  // 对图片进行处理
  readImage(file){
    return new Promise((resolve,reject) => {
      let data = ""//保存地址
      const reader = new FileReader()
      // 读取文件并将文件以URL的形式保存在resulr属性中 base64格式
      reader.readAsDataURL(file)
      // 文件读取完成时触发
      reader.onload = async e => {
        const image = new Image()
        if(typeof e.target.result === 'object'){
          // 把Array Buffer转化为blob 如果是base64不需要
          data = window.URL.createObjectURL(new Blob([e.target.result]))
        }else{
          data = e.target.result//base64格式图片地址
        }
        image.src = data
        image.onload = async e => {
          const canvas = document.createElement('canvas')
          const context = canvas.getContext('2d')
          const { width: originWidth, height: originHeight } = image
          // 目标尺寸
          let targetWidth = originWidth
          let targetHeight = originHeight
          // 获得长宽比例
          const scale = targetWidth / targetHeight;
          //获取压缩后的图片宽度,如果width为-1,默认原图宽度
          targetWidth = this.width == -1 ? targetWidth : this.width;
          //获取压缩后的图片高度,如果width为-1,默认原图高度
          targetHeight = this.width == -1 ? targetHeight : parseInt(this.width / scale);
          canvas.width = targetWidth
          canvas.height = targetHeight
          context.clearRect(0, 0, targetWidth, targetHeight)
          context.fillStyle = '#fff'
          // 图片绘制
          context.drawImage(image, 0, 0, targetWidth, targetHeight)
          let dataUrl = canvas.toDataURL(file.type, this.quality || 0.92)//0.92为压缩比,可根据需要设置,设置过小会影响图片质量
          let fileObj = await this.dataURItoBlob(dataUrl,file.type,file)
          resolve(fileObj)
        }
      }
      reader.onerror = e => {
        Message.error('图片读取出错!')
      }
    })
  }
  // base64转为Blob
  async dataURItoBlob(dataurl,type = "image/png",file){
    return new Promise((resolve,reject) => {
      const filename = 'file'
      let arr = dataurl.split(',')
      let mime = arr[0].match(/:(.*?);/)[1]
      let suffix = mime.split('/')[1]
      let bstr = atob(arr[1])
      let n = bstr.length
      let u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      const miniFile = new File([u8arr], `${filename}.${suffix}`, {type: mime})
      console.log({
        file:miniFile,
        origin:file,
        beforeKB:Number((file.size / 1024).toFixed(2)),
        afterKB:Number((miniFile.size / 1024).toFixed(2)),
      })
      resolve({
        file:miniFile,
        origin:file,
        beforeKB:Number((file.size / 1024).toFixed(2)),
        afterKB:Number((miniFile.size / 1024).toFixed(2))
      })
    })
  }
  // 判断上传的图片格式是否符合要求
  isImage(image){
    return /\.(jpg|png|bmp|jpeg|webp|gif)$/.test(image.name)
  }
  // 判断图片是否过大
  isLimitSize(image){
    const isLimitSize = this.targetSize < (image.size / 1024 / 1024)
    // console.log('size',image.size)
    // console.log('isLimitSize',isLimitSize)
    // console.log('targetSize',this.targetSize)
    // console.log(image)
    if(!isLimitSize){
      return true
    }else{
      return false
    }
  }
}

export default Compress

在所需要的页面调用

import Compress from '../../common/utils/Compress';

通过调用方法得到图片的file格式 

// 文件(res.tempFiles[0]是uniapp中chooseImage方法得到的) 宽度 质量 图片尺寸(1是1024 * 1024)
let imgfile = new Compress(res.tempFiles[0], 600, 0.8, 1); 
let res2 = await imgfile.compressUpload(); // 记得配合 async 使用
console.log('res2', res2.file); // 得到图片的file格式

根据接口的需要,我将file转换为blob格式,如下

 // res2.file就是上面我们得到的file图片   res.tempFiles[0].type是uniapp中chooseImage方法的图片类型
 let blob = new Blob([res2.file], {type: res.tempFiles[0].type})
            let reader = new  FileReader()
            reader.readAsDataURL(blob)
            reader.onload = (e)=> {
              // console.log('e', e);
              // 其中e.currentTarget.result就是我们需要的图片格式blob
            
              // 调用uniapp中的图片文件上传方法
              uni.uploadFile({
                url: ,  // 接口地址
                fileType: 'image',  // 图片类型
                filePath: e.currentTarget.result,  // blob图片格式
                name: 'file',
                formData: {
                  TOKEN: '',
                },
                success(res1) {
            

              
                },
              });
            }


            }

希望能帮到你们,求个点赞

完整代码如下:

// 调用手机相机(使用了uniapp)
pictureClick() {
  let that = this;
  uni.chooseImage({
    count: 1,
    sourceType: ['camera'], // camera拍照,album相册
    success: async res => {
      this.tempFilePaths = res.tempFilePaths;
      this.Imgs = res.tempFilePaths[0];

      let imgfile = new Compress(res.tempFiles[0], 600, 0.8, 1);
      let res2 = await imgfile.compressUpload();

      let blob = new Blob([res2.file], {type: res.tempFiles[0].type})
      let reader = new  FileReader()
      reader.readAsDataURL(blob)
      reader.onload = (e)=> {
      
        uni.uploadFile({
          url: '', // 接口地址
          fileType: 'image',
          filePath: e.currentTarget.result,
          name: 'file',
          formData: {
            type: 10,
            TOKEN: '',
          },
          success(res1) {
            // 后端人脸识别接口


              } else if (res.status === 1) {
                uni.showToast({
                  title: res.msg,
                  icon: 'none',
                  duration: 2000,
                });
              } else {
                alert(res.msg);
              }
            });
          },
        });
      }

    },
  });
},
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值