import React, { useEffect, useState } from 'react'; import { UploadOutlined } from '@ant-design/icons'; import type { UploadFile, UploadProps } from 'antd'; import { Button, Form, message, Upload } from 'antd'; interface OSSDataType { dir: string; expire: string; host: string; accessId: string; policy: string; signature: string; } interface AliyunOSSUploadProps { value?: UploadFile[]; onChange?: (fileList: UploadFile[]) => void; } const AliyunOSSUpload = ({ value, onChange }: AliyunOSSUploadProps) => { const [OSSData, setOSSData] = useState<OSSDataType>(); // Mock get OSS api // https://help.aliyun.com/document_detail/31988.html const mockGetOSSData = () => ({ dir: 'user-dir/', expire: '1577811661', host: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload', accessId: 'c2hhb2RhaG9uZw==', policy: 'eGl4aWhhaGFrdWt1ZGFkYQ==', signature: 'ZGFob25nc2hhbw==', }); const init = async () => { try { const result = await mockGetOSSData(); setOSSData(result); } catch (error) { message.error(error as string); } }; useEffect(() => { init(); }, []); const handleChange: UploadProps['onChange'] = ({ fileList }) => { console.log('Aliyun OSS:', fileList); onChange?.([...fileList]); }; const onRemove = (file: UploadFile) => { const files = (value || []).filter((v) => v.url !== file.url); if (onChange) { onChange(files); } }; const getExtraData: UploadProps['data'] = (file) => ({ key: file.url, OSSAccessKeyId: OSSData?.accessId, policy: OSSData?.policy, Signature: OSSData?.signature, }); const beforeUpload: UploadProps['beforeUpload'] = async (file) => { if (!OSSData) return false; const expire = Number(OSSData.expire) * 1000; if (expire < Date.now()) { await init(); } const suffix = file.name.slice(file.name.lastIndexOf('.')); const filename = Date.now() + suffix; // @ts-ignore file.url = OSSData.dir + filename; return file; }; const uploadProps: UploadProps = { name: 'file', fileList: value, action: OSSData?.host, onChange: handleChange, onRemove, data: getExtraData, beforeUpload, }; return ( <Upload {...uploadProps}> <Button icon={<UploadOutlined />}>Click to Upload</Button> </Upload> ); }; const App: React.FC = () => ( <Form labelCol={{ span: 4 }}> <Form.Item label="Photos" name="photos"> <AliyunOSSUpload /> </Form.Item> </Form> ); export default App;