地址

github:https://github.com/fengyuanchen/compressorjs
演示地址:https://fengyuanchen.github.io/compressorjs/

方法代码

  1. new Compressor(file, {
  2. quality: 0.4, // 压缩等级
  3. success(result) {
  4. console.log((result.size / 1024 / 1024).toFixed(4), '压缩后大小');
  5. },
  6. error(err) {
  7. console.log(err, '压缩错误');
  8. },
  9. });

react 示例

使用 antd 的 Upload 插件写的小 demo

演示

图片压缩.gif

代码

index.js

  1. import React, { useState, useEffect } from 'react';
  2. import { Upload, message, Radio } from 'antd';
  3. import { InboxOutlined } from '@ant-design/icons';
  4. import Compressor from 'compressorjs';
  5. import styles from './index.less';
  6. const { Dragger } = Upload;
  7. const options = [
  8. { label: '0.2', value: 0.2 },
  9. { label: '0.4', value: 0.4 },
  10. { label: '0.6', value: 0.6 },
  11. { label: '0.8', value: 0.8 },
  12. ];
  13. const ImgCompressor = () => {
  14. const [quality, setQuality] = useState(0.8);
  15. const [fileData, setFileData] = useState({ size: 0, url: '', file: null });
  16. const [compressorData, setCompressorData] = useState({ size: 0, url: '', file: null });
  17. const setData = (file, compre) => {
  18. setFileData(file);
  19. setCompressorData(compre);
  20. };
  21. // file/blob 转换为 url
  22. const transformUrl = file => {
  23. let url = '';
  24. if (window.createObjectURL != undefined) { // basic
  25. url = window.createObjectURL(file);
  26. } else if (window.URL != undefined) { // mozilla(firefox)
  27. url = window.URL.createObjectURL(file);
  28. } else if (window.webkitURL != undefined) { // webkit or chrome
  29. url = window.webkitURL.createObjectURL(file);
  30. }
  31. return url;
  32. }
  33. // 压缩图片
  34. const compressorFn = file => {
  35. return new Promise(resolve => {
  36. const fileData = { // 压缩前文件
  37. size: (file.size / 1024 / 1024).toFixed(4),
  38. url: transformUrl(file),
  39. file,
  40. };
  41. new Compressor(file, {
  42. quality,
  43. success(result) {
  44. const compressorData = { // 压缩后文件
  45. size: (result.size / 1024 / 1024).toFixed(4),
  46. url: transformUrl(result),
  47. file: result,
  48. };
  49. fileData.size === compressorData.size && message.info('所选压缩质量等级过小或图片大小过小,无需压缩');
  50. setData(fileData, compressorData);
  51. resolve(result);
  52. },
  53. error(err) {
  54. // 压缩报错的话 返回原图片
  55. message.info(`压缩失败,原图上传!${err}。`);
  56. setData(fileData, fileData);
  57. resolve(file);
  58. },
  59. });
  60. });
  61. }
  62. // 压缩等级更新后重新压缩
  63. useEffect(() => {
  64. fileData.file && compressorFn(fileData.file)
  65. }, [quality]);
  66. // 上传组件 props
  67. const props = {
  68. name: 'file',
  69. accept: 'image/*',
  70. multiple: true,
  71. action: 'https://172.16.59.21/upload',
  72. fileList: [],
  73. transformFile(file) { // 上传前转换文件
  74. return compressorFn(file);
  75. },
  76. // onChange(info) { // 虽然使用了 transformFile 方法转换了文件并上传,但是此位置仍然是返回原始文件
  77. // const { status } = info.file;
  78. // if (status === 'uploading') {
  79. // // console.log(info.file, info.fileList, 'uploading');
  80. // }
  81. // if (status === 'done') {
  82. // message.success(`${info.file.name} 上传成功`);
  83. // } else if (status === 'error') {
  84. // message.error(`${info.file.name} 上传失败`);
  85. // console.log(info, info.fileList, '上传失败');
  86. // }
  87. // },
  88. };
  89. return (
  90. <div className={styles['compressor']}>
  91. <div className={styles['proportion']}>
  92. 选择压缩等级:
  93. <Radio.Group
  94. options={options}
  95. onChange={e => setQuality(e.target.value)}
  96. value={quality}
  97. optionType="button"
  98. />
  99. </div>
  100. <Dragger {...props}>
  101. <p className="ant-upload-drag-icon">
  102. <InboxOutlined />
  103. </p>
  104. <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
  105. <p className="ant-upload-hint">支持单个或多个上传</p>
  106. </Dragger>
  107. <div className={styles['img-list']}>
  108. <div>
  109. <div className={styles['img-list-header']}>
  110. <span>压缩前大小:{fileData.size}M</span>
  111. </div>
  112. {fileData.url && <img src={fileData.url} alt="加载失败" />}
  113. </div>
  114. <div>
  115. <div className={styles['img-list-header']}>
  116. <span>压缩后大小:{compressorData.size}M</span>
  117. {!!fileData.size && <span>节省空间:{`${((fileData.size - compressorData.size) / fileData.size * 100).toFixed(2)}%`}</span>}
  118. </div>
  119. {compressorData.url && <img src={compressorData.url} alt="加载失败" />}
  120. </div>
  121. </div>
  122. </div>
  123. );
  124. };
  125. export default ImgCompressor;

index.less

  1. .compressor {
  2. .proportion {
  3. margin-bottom: 20px;
  4. }
  5. .img-list {
  6. display: flex;
  7. justify-content: space-around;
  8. margin-top: 30px;
  9. font-size: 16px;
  10. > div {
  11. width: 330px;
  12. height: 500px;
  13. img {
  14. max-width: 100%;
  15. max-height: 100%;
  16. }
  17. }
  18. .img-list-header {
  19. > span {
  20. margin-right: 24px;
  21. }
  22. }
  23. }
  24. }

参考资料

在React中利用compressorjs对图片进行压缩上传_weixin_44517846的博客-CSDN博客