本文介绍: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类似那种底层算法)
略略略~~ 有问题留言