react antd-mobile v2图片选择器ImagePicker压缩图片上传腾讯云COS处理方案

本文介绍:react移动端 antd-mobile V2版本使用图片选择器 ImagePicker时,前端压缩图片并且上传腾讯云COS

如果不上传腾讯云,纯选择压缩,可查看:antd-mobile-v2图片选择器ImagePicker压缩图片处理方案

后端出接口获取cos配置信息,文中GET 请求接口可看 另一个博客axios常用请求封装

腾讯云JSSDK:https://cloud.tencent.com/document/product/436/11459

安装腾讯云cos
注意腾讯云后台管理,配置cos的put、get、del等跨域信息(*最好,否则本地调试不能使用。前端不知道的要运维配置)

yarn add cos-js-sdk-v5
或
npm install cos-js-sdk-v5

父组件:(非必须,不想抽离可以直接怼一个页面上)

项目@引用如果没有配置,可用 …/ 相对路径方式。
若研究可参考我另一个项目:https://blog.csdn.net/weixin_44461275/article/details/122587585

	// 引用
	import ImgUpload from '@/components/ImgUpload';
	
	// 变量声明
	const [uploadImgList, setUploadImgList] = useState([]); // uploadImgList最终结果的图片列表
	const [showBigObj, setShowBigObj] = useState({ // 点击放大记录信息 -- 非必须
    	visiable: false,
    	url: ""
  	});

	// 调用
	<ImgUpload
        length={3} //每行显示数量
        multiple //是否多选
        maxNum={5} //长度限制+提示(自定义参数,二次封装的)
        handleImgList={setUploadImgList}
        onImageClick={(idx, files) => handleShowBigImg(true, files[idx].url)} //点击方法使用
    />

子组件:

import React, { useState } from 'react';
import { ImagePicker, Toast } from 'antd-mobile';
import COS from 'cos-js-sdk-v5';  //腾讯云cos
import { GET } from '@/utils/request'; //封装的GET请求,我这边项目是get请求接口获取cos配置信息 博客:https://blog.csdn.net/weixin_44461275/article/details/122230473有介绍

import './index.css';

// 文档:腾讯云JSSDK
// https://cloud.tencent.com/document/product/436/11459

const ImagePickerExample = (props) => {
  const { handleImgList, maxNum } = props;
  const [imgList, setImgList] = useState([]);

  function convertImgToBase64(url, file, callback, outputFormat) {
    if(file.size <= 5e5) return callback(url); //小于500kb 不压缩 -- 非必须
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext('2d');
    let img = new Image;
    img.crossOrigin = 'Anonymous';
    img.onload = function() {
      let width = img.width;
      let height = img.height;
      let bili = Math.round(width / 750) || 1; // 数据比例根据实际项目调整
      let rate = 1.5 / bili;
      canvas.width = width * rate;
      canvas.height = height * rate;
      ctx.drawImage(img, 0, 0, width, height, 0, 0, width * rate, height * rate);
      let dataURL = canvas.toDataURL(outputFormat || 'image/jpeg', 0.9); //0.9可改其他的,清晰度根据实际项目调整 0-1范围
      callback.call(this, dataURL);
      canvas = null;
    }
    img.src = url;
  }

  const uploadImg = (imgObj) => {
    return new Promise((resolve, reject) => {
      GET("uploadCos")
        .then(res => {
          const credentials = res.data.credentials;
          let cos = new COS({
            SecretId: credentials.tmpSecretId, // 文档是下面两个,实际配置报错,查看源代码是这两个
            SecretKey: credentials.tmpSecretKey,
            // TmpSecretId: credentials.tmpSecretId,
            // TmpSecretKey: credentials.tmpSecretKey,
            SecurityToken: credentials.sessionToken,
            // 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
            StartTime: res.data.startTime, // 时间戳,单位秒,如:1580000000
            ExpiredTime: res.data.expiredTime, // 时间戳,单位秒,如:1580000000
          })

          convertImgToBase64(imgObj.url, imgObj.file, (convertImg) => {
            const KeyStr = 'dme-wechat/' + imgObj.file.name + '?_t=' + (new Date).getTime() + Math.random() * 1e18;
            cos.putObject(
              {
                Bucket: res.data.bucketName,//存储桶名称,必须字段
                Region: res.data.regionName,//地域名字,必须字段
                StorgeClass: 'STANDARD',
                Key: KeyStr, // 必须字段
                Body: convertImg,
              }, (err, data) => {
                if (data) {
                  resolve({
                    ...imgObj,
                    fileUrl: `https://${data.Location}`
                  })
                }
                reject();
              }
            );
          })
        })
        .catch(function (res) {
          reject();
        })
    })
  };

  // 新增-删除 图片事件
  function onChange(files, type, index) {
    if (maxNum && files.length > maxNum) Toast.info(`最大允许上传${maxNum}张图片`, 2, '', false);
    files = maxNum ? files.slice(0, maxNum) : files;
    console.log(files, type, index);
    if (type === 'add') {
      let taskAll = files.map(ii => {
        if (ii.fileUrl) {
          return ii;
        } else {
          return uploadImg(ii)
        }
      })

      Toast.loading('上传中...', 1000, '', false);
      Promise.all(taskAll).then(res => {
        Toast.hide();
        setImgList(res); // 选择器列表
        handleImgList(res.map(ii => ii.fileUrl)); // 传递给父级
      }).catch(function (res) {
        Toast.hide();
        Toast.info(`上传失败,请稍后重试~`, 2, '', false);
      })
    } else {
      setImgList(files); // 选择器列表
      handleImgList(files.map(ii => ii.fileUrl)); // 传递给父级
    }
  }

  return (
    <ImagePicker
      files={imgList}
      onChange={onChange}
      selectable={maxNum && imgList.length < maxNum} //长度限制
      {
      	...props
      }
    />
  )
}

export default ImagePickerExample

每个公司新项目要求很可能不一致,活学活用。
canvas前端压缩,无非是压缩宽高、清晰度这两个方面。专业不失真,纯压缩的压缩算法前端没多少会的(美图秀秀、tinypng类似那种底层算法)


略略略~~ 有问题留言

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值