地址
github:https://github.com/fengyuanchen/compressorjs
演示地址:https://fengyuanchen.github.io/compressorjs/
方法代码
new Compressor(file, {
quality: 0.4, // 压缩等级
success(result) {
console.log((result.size / 1024 / 1024).toFixed(4), '压缩后大小');
},
error(err) {
console.log(err, '压缩错误');
},
});
react 示例
演示
代码
index.js
import React, { useState, useEffect } from 'react';
import { Upload, message, Radio } from 'antd';
import { InboxOutlined } from '@ant-design/icons';
import Compressor from 'compressorjs';
import styles from './index.less';
const { Dragger } = Upload;
const options = [
{ label: '0.2', value: 0.2 },
{ label: '0.4', value: 0.4 },
{ label: '0.6', value: 0.6 },
{ label: '0.8', value: 0.8 },
];
const ImgCompressor = () => {
const [quality, setQuality] = useState(0.8);
const [fileData, setFileData] = useState({ size: 0, url: '', file: null });
const [compressorData, setCompressorData] = useState({ size: 0, url: '', file: null });
const setData = (file, compre) => {
setFileData(file);
setCompressorData(compre);
};
// file/blob 转换为 url
const transformUrl = file => {
let url = '';
if (window.createObjectURL != undefined) { // basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
}
// 压缩图片
const compressorFn = file => {
return new Promise(resolve => {
const fileData = { // 压缩前文件
size: (file.size / 1024 / 1024).toFixed(4),
url: transformUrl(file),
file,
};
new Compressor(file, {
quality,
success(result) {
const compressorData = { // 压缩后文件
size: (result.size / 1024 / 1024).toFixed(4),
url: transformUrl(result),
file: result,
};
fileData.size === compressorData.size && message.info('所选压缩质量等级过小或图片大小过小,无需压缩');
setData(fileData, compressorData);
resolve(result);
},
error(err) {
// 压缩报错的话 返回原图片
message.info(`压缩失败,原图上传!${err}。`);
setData(fileData, fileData);
resolve(file);
},
});
});
}
// 压缩等级更新后重新压缩
useEffect(() => {
fileData.file && compressorFn(fileData.file)
}, [quality]);
// 上传组件 props
const props = {
name: 'file',
accept: 'image/*',
multiple: true,
action: 'https://172.16.59.21/upload',
fileList: [],
transformFile(file) { // 上传前转换文件
return compressorFn(file);
},
// onChange(info) { // 虽然使用了 transformFile 方法转换了文件并上传,但是此位置仍然是返回原始文件
// const { status } = info.file;
// if (status === 'uploading') {
// // console.log(info.file, info.fileList, 'uploading');
// }
// if (status === 'done') {
// message.success(`${info.file.name} 上传成功`);
// } else if (status === 'error') {
// message.error(`${info.file.name} 上传失败`);
// console.log(info, info.fileList, '上传失败');
// }
// },
};
return (
<div className={styles['compressor']}>
<div className={styles['proportion']}>
选择压缩等级:
<Radio.Group
options={options}
onChange={e => setQuality(e.target.value)}
value={quality}
optionType="button"
/>
</div>
<Dragger {...props}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p className="ant-upload-hint">支持单个或多个上传</p>
</Dragger>
<div className={styles['img-list']}>
<div>
<div className={styles['img-list-header']}>
<span>压缩前大小:{fileData.size}M</span>
</div>
{fileData.url && <img src={fileData.url} alt="加载失败" />}
</div>
<div>
<div className={styles['img-list-header']}>
<span>压缩后大小:{compressorData.size}M</span>
{!!fileData.size && <span>节省空间:{`${((fileData.size - compressorData.size) / fileData.size * 100).toFixed(2)}%`}</span>}
</div>
{compressorData.url && <img src={compressorData.url} alt="加载失败" />}
</div>
</div>
</div>
);
};
export default ImgCompressor;
index.less
.compressor {
.proportion {
margin-bottom: 20px;
}
.img-list {
display: flex;
justify-content: space-around;
margin-top: 30px;
font-size: 16px;
> div {
width: 330px;
height: 500px;
img {
max-width: 100%;
max-height: 100%;
}
}
.img-list-header {
> span {
margin-right: 24px;
}
}
}
}