文章目录
本文将介绍两种方式进行批量上传图片(原始input/antdUpload)
两种方式的区别
1. 原始input是将图片存为一个对象数组,将不合格的图片过滤掉之后,一次性提交给后端
2. antd-Upload是循环调用后端接口(上传一张的接口)上传图片,遇到不合格的可以跳过
一、原始input
(1)页面使用input HTML
1. 编辑页面元素
分别设置type、mutiple,accept,且可以绑定ref
<Item label={'目标文件'}>
<div>
选择图片
<input
ref={uploadRef}
type="file"
accept="image/*"
multiple
onChange={handlePictureChange}
/>
</div>
</Item>
2. 设置ref
const uploadRef = useRef<any>();
(2)编写onChange函数
1. 定义formData
- 标准形式的formData,但是在使用中需要变成
formData.current
const formData = useRef<FormDataProps>(new FormData());
- 非标准形式的fromData
const formData = new FormData();
2. 编写onChange函数
下面使用的是非标准形式的formdata
const handlePictureChange = (e: any): void => {
console.log(uploadRef.current);//通过current可以拿到files
// debugger;
//定义fileArr数组将files存入该数组
const fileArr = [...uploadRef.current.files];
//对批量上传的图片数量做判断
if (fileArr.length > 200) {
message.error('图片数量较多');
} else {
fileArr.forEach((item: any, index: any) => {
//这是我编写的验证图片格式函数,下面会介绍
const picType = judgePictureType(item.type);
if (picType) {
//图片格式正确
formData.append('file', item)
} else {
message.error('请确保图片格式正确!');
}
});
//下面这段代码可以看到格式正确,且存入了formData
// formData.forEach((value: any, key: any) => {
// console.log(value, key);
// });
}
};
3. 上传图片时
当点击页面的提交button时,下面使用的标准形式的formData
const handleSubmit: React.FormEventHandler<HTMLFormElement> = useCallback(
(e): void => {
e.preventDefault();
validateFields(async (err, values) => {
//判断formdata是否为空
if (!err && formData.current.get('file')) {
try {
// 可以看见formData 的值
formData.current.forEach((value: any, key: any) => {
console.log(value, key);
});
//后端接口
piliaruku(formData.current);
} catch (e) {
message.error(e.message || '添加失败');
}
} else {
message.error('提交格式有误!');
}
});
},
[formData, validateFields],
);
4. 图片格式校验函数
export function judgePictureType(type: string): boolean {
const isJPG = type === 'image/jpeg';
const isPNG = type === 'image/png';
const isBMP = type === 'image/bmp';
const isPic = isJPG || isPNG || isBMP;
return isPic ? true : false;
}
(3)后端接口
此时,不能使用封装好的post,需要使用axios.post
1. 封装好的post
export async function post<R = any, P = any>(
url: string,
data?: P,
config?: AxiosRequestConfig,
): Promise<ResponseReturn<R>> {
const response = await http.post(url, data, config);
return response.data;
}
2. 原生post
import axios from 'axios';
export async function piliaruku(params: any): Promise<ResponseReturn<PliliangrukuResponse>> {
return await axios.post('/piliangruku', params, {
//设置批量上传的请求头
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
3. 返回值类型
export type PliliangrukuResponse = null;
二、antd-Upload实现批量上传
(1)使用antd-Upload的directory方式进行多文件上传
1. html
<Item label={'目标文件'} className={styles['input-upload']}>
<Upload
{...uploadProps}
showUploadList={false} //设置页面不展示上传的文件列表
directory
multiple
>
<Button>
<Icon type="upload" /> 请选择文件夹
</Button>
</Upload>
</Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={loading}>
{loading ? '上传中,请不要重复提交' : '提交'}
</Button>
</Form.Item>
2. uploadProps
在这里使用beforeUpload对图片做格式判断没有任何意义,如果在uploadProps使用上传函数接口,不管是在beforeUpload还是onChange,都会上传。
举个例子,假如要求图片不超过200,你可以在beforeUpload中使用fileList进行判断,但是如果文件夹中有260张,但其实还是对260张进行了暂存。也就是说循环上传无法停止。
const file_list = useRef<any>([]);
const uploadProps = {
accept: 'image/*',
beforeUpload(): boolean {
return false;
},
async onChange(info: UploadChangeParam<UploadFile<any>>): Promise<void> {
if (!info.file) return Promise.reject(new Error('请选择图片'));
try {
file_list.current = info.fileList;
} catch (e) {
console.error(e);
}
},
};
(2)对提交的照片进行格式判断和提交给后端
1. 设置图片变量
const [loading, setLoading] = useState(false); //loading状态
const [fileNum, setFileNum] = useState(0); //文件总数
const [fileSuccessNum, setFileSuccessNum] = useState(0);//文件成功的数量
2. 图片上传函数
const handleSubmit: React.FormEventHandler<HTMLFormElement> = useCallback((e): void => {
e.preventDefault();
setLoading(true); //图片上传开始
if (file_list.current.length > 200) {
message.error('图片数量较多');
return;
}
const fileArr: Promise<ResponseReturn<PliliangrukuResponse>>[] = [];
file_list.current.forEach((file: any) => {
const reg = /(\.png|\.jpg|\.jpeg)$/g;
//判断格式
if (!reg.test(file.name)) {
//我这里设置了一个变量将格式不正确的图片存入这个数组中
const messageErr = file.name + ' 格式不正确';
setErrFile(errFile => [...errFile, messageErr]);
} else {
const formData = new FormData();
formData.append('file', file.originFileObj);
//后端接口
fileArr.push(pilianrukuXunhuan(formData));
}
});
setFileNum(fileArr.length); //总数
Promise.all(fileArr)
.then(res => {
setFileSuccessNum(res.length); //上传成功的数量
setLoading(false); //图片上传结束
setConfirmModal(true);
})
.catch(e => {
message.error(e);
})
.finally(() => {
setLoading(false);//图片上传失败的状态
});
}, []);
(3)后端接口
因为图片上传函数使用了promise封装,所以对后端提交函数做了部分修改
export async function pilianrukuXunhuan(params: any): Promise<ResponseReturn<PliliangrukuResponse>> {
const res: any = await axios.post('/..../piliangruku', params, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
if (res.status === 200 && res.data.code === 0) {
return Promise.resolve(res.data);
}
return Promise.reject(new Error('上传出错'));
}