优化Upload
parent
d6ada39fd0
commit
ea129b523c
|
|
@ -1,6 +1,6 @@
|
|||
import { PlusOutlined, UploadOutlined, VideoCameraAddOutlined } from "@ant-design/icons";
|
||||
import { Upload as AntUpload, Button, message, Modal } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
|
||||
/**
|
||||
* 文件上传组件
|
||||
|
|
@ -29,6 +29,9 @@ const Upload = (props) => {
|
|||
const [previewVisible, setPreviewVisible] = useState(false);
|
||||
const [previewImage, setPreviewImage] = useState("");
|
||||
|
||||
// 记录已经提示过错误的文件uid,避免重复提示
|
||||
const warnedFileUids = useRef(new Set());
|
||||
|
||||
// 预设的文件格式
|
||||
const imageAccept = ".jpg,.jpeg,.png";
|
||||
const documentAccept = ".pdf,.doc,.docx";
|
||||
|
|
@ -137,66 +140,99 @@ const Upload = (props) => {
|
|||
};
|
||||
|
||||
// 文件状态改变
|
||||
const handleChange = ({ file, fileList }) => {
|
||||
const handleChange = ({ fileList }) => {
|
||||
console.log(fileList);
|
||||
const acceptList = accept ? accept.split(",") : [];
|
||||
const ratioArr = ratio ? ratio.split("*") : [];
|
||||
const suffix = file.name.substring(
|
||||
file.name.lastIndexOf("."),
|
||||
file.name.length,
|
||||
);
|
||||
const maxSize = size * 1024 * 1024;
|
||||
|
||||
// 验证文件格式
|
||||
if (acceptList.length > 0 && !acceptList.includes(suffix)) {
|
||||
message.warning(`只能上传${acceptTip}格式的文件`);
|
||||
const filtered = fileList.filter(item => item.uid !== file.uid);
|
||||
onChange?.(filtered);
|
||||
return;
|
||||
}
|
||||
// 对整个fileList进行验证和过滤
|
||||
const validateFiles = async (files) => {
|
||||
const validFiles = [];
|
||||
const invalidFiles = [];
|
||||
|
||||
// 验证文件大小
|
||||
if (maxSize && file.size > maxSize) {
|
||||
message.warning(`文件大小不能超过${size}M`);
|
||||
const filtered = fileList.filter(item => item.uid !== file.uid);
|
||||
onChange?.(filtered);
|
||||
return;
|
||||
}
|
||||
for (const fileItem of files) {
|
||||
const suffix = fileItem.name?.substring(
|
||||
fileItem.name.lastIndexOf("."),
|
||||
fileItem.name.length,
|
||||
) || "";
|
||||
|
||||
// 验证图片分辨率
|
||||
if (ratioArr.length === 2 && file.type?.startsWith("image/")) {
|
||||
const validateImageResolution = (imageUrl) => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
if (img.width !== +ratioArr[0] || img.height !== +ratioArr[1]) {
|
||||
message.warning(`只能上传${ratio}分辨率的图片`);
|
||||
const filtered = fileList.filter(item => item.uid !== file.uid);
|
||||
onChange?.(filtered);
|
||||
return;
|
||||
// 验证文件格式
|
||||
if (acceptList.length > 0 && !acceptList.includes(suffix)) {
|
||||
invalidFiles.push(fileItem);
|
||||
// 只提示未提示过的文件
|
||||
if (!warnedFileUids.current.has(fileItem.uid)) {
|
||||
warnedFileUids.current.add(fileItem.uid);
|
||||
message.warning(`${fileItem.name}:只能上传${acceptTip}格式的文件`);
|
||||
}
|
||||
onChange?.(fileList);
|
||||
};
|
||||
img.src = imageUrl;
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果有现成的URL则直接使用,否则使用FileReader读取本地文件
|
||||
if (file.url) {
|
||||
validateImageResolution(file.url);
|
||||
// 验证文件大小
|
||||
if (maxSize && fileItem.size > maxSize) {
|
||||
invalidFiles.push(fileItem);
|
||||
// 只提示未提示过的文件
|
||||
if (!warnedFileUids.current.has(fileItem.uid)) {
|
||||
warnedFileUids.current.add(fileItem.uid);
|
||||
message.warning(`${fileItem.name}:文件大小不能超过${size}M`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 验证图片分辨率(异步)
|
||||
if (ratioArr.length === 2 && fileItem.type?.startsWith("image/")) {
|
||||
const validateImageResolution = (imageUrl) => {
|
||||
return new Promise((resolve) => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
const isValid = img.width === +ratioArr[0] && img.height === +ratioArr[1];
|
||||
if (!isValid) {
|
||||
// 只提示未提示过的文件
|
||||
if (!warnedFileUids.current.has(fileItem.uid)) {
|
||||
warnedFileUids.current.add(fileItem.uid);
|
||||
message.warning(`${fileItem.name}:只能上传${ratio}分辨率的图片`);
|
||||
}
|
||||
}
|
||||
resolve(isValid);
|
||||
};
|
||||
img.onerror = () => resolve(false);
|
||||
img.src = imageUrl;
|
||||
});
|
||||
};
|
||||
|
||||
const validResolution = fileItem.url
|
||||
? await validateImageResolution(fileItem.url)
|
||||
: await new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
validateImageResolution(e.target.result).then(resolve);
|
||||
};
|
||||
reader.onerror = () => resolve(false);
|
||||
reader.readAsDataURL(fileItem.originFileObj);
|
||||
});
|
||||
|
||||
if (!validResolution) {
|
||||
invalidFiles.push(fileItem);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
validFiles.push(fileItem);
|
||||
}
|
||||
else {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
validateImageResolution(e.target.result);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
onChange?.(fileList);
|
||||
}
|
||||
|
||||
return { validFiles, invalidFiles };
|
||||
};
|
||||
|
||||
// 执行验证并更新
|
||||
validateFiles(fileList).then(({ validFiles }) => {
|
||||
onChange?.(validFiles);
|
||||
});
|
||||
};
|
||||
|
||||
// 删除文件
|
||||
const handleRemove = (file) => {
|
||||
// 清理该文件的提示记录
|
||||
warnedFileUids.current.delete(file.uid);
|
||||
if (!file.originFileObj)
|
||||
onGetRemoveFile?.(file);
|
||||
return onRemove?.(file);
|
||||
|
|
|
|||
Loading…
Reference in New Issue