文章目录
前言
下载依赖
bash
npm install browser-image-compression -S
我这里是react 使用,本质上vue也是相同的用法,都是js,以及input调用
用的input标签进行上传,原汁原味,不使用组件,因为组件库界面不喜欢。
一、编写utils方法
utils/common.ts文件里面写公共方法
js
import imageCompression from 'browser-image-compression';
/**
* 压缩图片文件
* @param file - 要压缩的图片文件
* @param maxSizeMB - 最大文件大小(MB),超过此大小才压缩,默认 1MB
* @returns Promise<File> - 返回压缩后的图片文件(如果小于 maxSizeMB 则返回原文件)
*/
export async function compressImage(file: File, maxSizeMB: number = 1): Promise<File> {
// 检查文件大小(MB)
const fileSizeMB = file.size / 1024 / 1024;
// 如果文件小于等于 maxSizeMB,不需要压缩,直接返回原文件
if (fileSizeMB <= maxSizeMB) {
return file;
}
// 根据文件大小动态设置压缩选项
// 注意:browser-image-compression 默认保持宽高比(等比例压缩)
const options = {
maxSizeMB: maxSizeMB, // 目标文件大小(MB)
maxWidthOrHeight: 1920, // 最大宽度或高度(会等比例缩放,保持宽高比)
useWebWorker: true, // 使用 Web Worker 进行压缩(不阻塞主线程)
fileType: file.type, // 保持原文件类型
// 压缩质量(0-1),如果不设置,库会根据 maxSizeMB 自动调整
// initialQuality: 0.8, // 可选:初始压缩质量
};
try {
const compressedFile = await imageCompression(file, options);
console.log(
`图片压缩完成: ${file.name}, 原始大小: ${fileSizeMB.toFixed(2)}MB, 压缩后: ${(compressedFile.size / 1024 / 1024).toFixed(2)}MB`
);
return compressedFile;
} catch (error) {
console.error('图片压缩失败:', error);
// 压缩失败时返回原文件
return file;
}
}
二、使用步骤
1.标签使用
代码如下(示例):
js
{/* 添加图片按钮 */}
<label className="block w-full border-2 border-dashed border-input rounded-lg cursor-pointer hover:border-primary transition-colors p-6 text-center">
<input
type="file"
accept="image/png,image/jpeg,image/jpg"
multiple
className="hidden"
onChange={async (e) => {
const fileList = e.target.files;
if (!fileList || fileList.length === 0) return;
// 将 FileList 转换为数组
const files = Array.from(fileList);
// 验证所有文件类型
const invalidFiles: File[] = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
if (!file.type.match(/^image\/(png|jpeg|jpg)$/)) {
invalidFiles.push(file);
}
}
if (invalidFiles.length > 0) {
alert('请上传 png、jpeg 或 jpg 格式的图片');
e.target.value = '';
return;
}
try {
// 压缩图片(如果大于 1MB)
const compressedFiles = await Promise.all(files.map((file) => compressImage(file, 1)));
// 构建 FormData,使用动态下标
const uploadFormData = new FormData();
for (let i = 0; i < compressedFiles.length; i++) {
uploadFormData.append(`images[${i}][file]`, compressedFiles[i]);
uploadFormData.append(`images[${i}][subPath]`, 'product/goods');
}
// 上传图片
CommonApi.uploadImages(uploadFormData)
.then((res) => {
if (Array.isArray(res.data)) {
const newAssets = res.data
.map((item: any, index: number) => {
if (item?.path) {
return {
scope: '',
file_name: files[index]?.name || '',
file_path: item.path,
sort_order: formData.assets.length + index,
alt_text: '',
};
}
return null;
})
.filter((asset): asset is NonNullable<typeof asset> => asset !== null);
if (newAssets.length > 0) {
// 执行赋值操作
} else {
console.error('上传图片接口返回的数据格式不正确:', res.data);
alert('上传图片失败,请重试');
}
} else {
console.error('上传图片接口返回的数据格式不正确:', res.data);
alert('上传图片失败,请重试');
}
})
.catch((error) => {
console.error('上传图片失败: ', error);
alert('上传图片失败,请重试');
});
} catch (error) {
console.error('压缩图片失败: ', error);
alert('处理图片失败,请重试');
}
// 清空input,允许重复上传同一文件
e.target.value = '';
}}
... 这里写你上传按钮或者图片图标
/>
2.分析
- label标签和input标签是联动的,把input隐藏, label内写其他的div,就可以做到点击触发上传
- 这是我的上传格式

- 返回值res.data是一个数组,
如下
js
{
"ret": 1,
"msg": "success",
"data": [
{
"name": "20251202zO8PwOslh7U19qNW40Tf7sNjYOkRNHGLKeXxNacl.jpg",
"path": "\/product\/goods\/20251202zO8PwOslh7U19qNW40Tf7sNjYOkRNHGLKeXxNacl.jpg",
"width": 1200,
"height": 1200
}
]
}
使用compressImage别忘记了引入

总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。