81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { message } from 'antd';
|
|
import { useImperativeHandle, useRef, forwardRef } from 'react';
|
|
import type { GetProp, UploadProps } from 'antd';
|
|
type FileTypeOrg = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
|
|
|
|
export type FileType = {
|
|
name: string;
|
|
size: number;
|
|
lastModified: number;
|
|
webkitRelativePath: string; // 包含name
|
|
};
|
|
|
|
const beforeUpload = (file: FileTypeOrg) => {
|
|
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
|
|
if (!isJpgOrPng) {
|
|
message.error('You can only upload JPG/PNG file!');
|
|
}
|
|
const isLt2M = file.size / 1024 / 1024 < 2;
|
|
if (!isLt2M) {
|
|
message.error('Image must smaller than 2MB!');
|
|
}
|
|
return isJpgOrPng && isLt2M;
|
|
};
|
|
type Props = {
|
|
onChange: (path: string) => void;
|
|
};
|
|
export const FileUpload = forwardRef<any, Props>((props, ref) => {
|
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
const onChange = async (e) => {
|
|
if (!beforeUpload(e.target.files[0])) {
|
|
return;
|
|
}
|
|
console.log(e.target.files);
|
|
const file = e.target.files[0];
|
|
const endType = file.name.split('.').pop();
|
|
const formData = new FormData();
|
|
formData.append('file', file, `avatar.${endType}`); // 保留文件夹路径
|
|
const res = await fetch('/api/upload', {
|
|
method: 'POST',
|
|
body: formData, //
|
|
headers: {
|
|
Authorization: 'Bearer ' + localStorage.getItem('token'),
|
|
},
|
|
}).then((res) => res.json());
|
|
if (res?.code === 200) {
|
|
console.log('res', res);
|
|
//
|
|
const [file] = res.data;
|
|
const { path } = file || {};
|
|
props?.onChange?.(path);
|
|
//
|
|
} else {
|
|
message.error(res.message || 'Request failed');
|
|
}
|
|
// 清理之前上传的文件
|
|
e.target.value = '';
|
|
};
|
|
// 把ref 传递到上层
|
|
useImperativeHandle(ref, () => {
|
|
return {
|
|
open: () => {
|
|
inputRef.current?.click();
|
|
},
|
|
};
|
|
});
|
|
return (
|
|
<div>
|
|
<input
|
|
style={{
|
|
display: 'none',
|
|
}}
|
|
ref={inputRef}
|
|
accept='image/*'
|
|
type='file'
|
|
multiple={false}
|
|
onChange={onChange}
|
|
/>
|
|
</div>
|
|
);
|
|
});
|