nili
8 months ago
8 changed files with 255 additions and 3 deletions
@ -0,0 +1,124 @@ |
|||
import { toMD5 } from '@/utils/encryptUtil'; |
|||
import OSS from 'ali-oss'; |
|||
import { message, Upload, UploadFile, UploadProps } from 'antd'; |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { getSts } from '../services/matrix/admin'; |
|||
|
|||
interface OSSUploadProps { |
|||
onUploadSuccess?: (fileUrl: string) => void; |
|||
onUploadError?: (error: any) => void; |
|||
} |
|||
|
|||
const OSSUpload: React.FC<OSSUploadProps> = ({ onUploadSuccess, onUploadError }) => { |
|||
const [uploading, setUploading] = useState(false); |
|||
const [fileList, setFileList] = useState<UploadFile[]>([]); |
|||
const [ossClient, setOssClient] = useState<OSS | null>(null); |
|||
const { Dragger } = Upload; |
|||
|
|||
useEffect(() => { |
|||
async function initOssClient() { |
|||
try { |
|||
const stsResponse = await getSts(); // 假设你有一个 getSTS 函数可以获取 STS 凭证
|
|||
if ( |
|||
!stsResponse.data || |
|||
!stsResponse.data.accessKeySecret || |
|||
!stsResponse.data.accessKeyId |
|||
) { |
|||
message.error('初始化失败,请稍后再试'); |
|||
return; |
|||
} |
|||
const client = new OSS({ |
|||
region: 'oss-cn-beijing', |
|||
accessKeyId: stsResponse.data.accessKeyId, |
|||
accessKeySecret: stsResponse.data.accessKeySecret, |
|||
stsToken: stsResponse.data.securityToken, |
|||
bucket: stsResponse.data.bucket, |
|||
}); |
|||
setOssClient(client); |
|||
} catch (error) { |
|||
message.error('初始化 OSS 客户端失败'); |
|||
if (onUploadError) { |
|||
onUploadError(error); |
|||
} |
|||
} |
|||
} |
|||
initOssClient(); |
|||
}, [onUploadError]); |
|||
|
|||
const onRemove = (file: UploadFile) => { |
|||
const files = (fileList || []).filter((v) => v.url !== file.url); |
|||
setFileList(files); |
|||
}; |
|||
|
|||
const handleUpload: UploadProps['customRequest'] = async (options) => { |
|||
const { file } = options; |
|||
if (file instanceof File) { |
|||
setUploading(true); |
|||
|
|||
try { |
|||
const md5 = await toMD5(file); |
|||
const fileName = `matrix/${md5}.${file.name.split('.').pop()}`; |
|||
await ossClient?.put(fileName, file, { |
|||
headers: { |
|||
'Content-Type': file.type, |
|||
}, |
|||
}); |
|||
const fileUrl = `https://apks.bzgames.cn/${fileName}`; |
|||
|
|||
if (onUploadSuccess) { |
|||
onUploadSuccess(fileUrl); |
|||
} |
|||
setUploading(false); |
|||
// 将上传成功的文件信息添加到 fileList
|
|||
setFileList((prevFileList) => [ |
|||
...prevFileList, |
|||
{ |
|||
uid: file.uid, |
|||
name: file.name + ':' + fileUrl, |
|||
status: 'done', |
|||
url: fileUrl, |
|||
}, |
|||
]); |
|||
} catch (error) { |
|||
message.error('文件上传失败'); |
|||
if (onUploadError) { |
|||
onUploadError(error); |
|||
} |
|||
setFileList((prevFileList) => [ |
|||
...prevFileList, |
|||
{ |
|||
uid: file.uid, |
|||
name: file.name, |
|||
status: 'error', |
|||
}, |
|||
]); |
|||
} finally { |
|||
setUploading(false); |
|||
} |
|||
} else { |
|||
message.error('上传文件类型错误'); |
|||
} |
|||
}; |
|||
|
|||
return ( |
|||
<Dragger |
|||
fileList={fileList} |
|||
multiple |
|||
customRequest={handleUpload} |
|||
onRemove={onRemove} |
|||
disabled={uploading || !ossClient} |
|||
onPreview={async (file) => { |
|||
await navigator.clipboard.writeText(file.url || ''); |
|||
message.success('链接复制成功 ' + file.url); |
|||
}} |
|||
> |
|||
<p className="ant-upload-drag-icon"> |
|||
<i className="anticon anticon-inbox" /> |
|||
</p> |
|||
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p> |
|||
<p className="ant-upload-hint">支持单个或批量上传。文件名将使用文件的 MD5 值命名。</p> |
|||
</Dragger> |
|||
); |
|||
}; |
|||
|
|||
export default OSSUpload; |
@ -0,0 +1,45 @@ |
|||
// @ts-ignore
|
|||
/* eslint-disable */ |
|||
import { request } from '@umijs/max'; |
|||
|
|||
/** 此处后端没有提供注释 GET /api/citrus/register/getApp */ |
|||
export async function getApp( |
|||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
|||
params: API.getAppParams, |
|||
options?: { [key: string]: any }, |
|||
) { |
|||
return request<API.RMatrixAppBo>('/api/citrus/register/getApp', { |
|||
method: 'GET', |
|||
params: { |
|||
...params, |
|||
}, |
|||
...(options || {}), |
|||
}); |
|||
} |
|||
|
|||
/** 此处后端没有提供注释 POST /api/citrus/register/sendCode */ |
|||
export async function sendCode( |
|||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
|||
params: API.sendCodeParams, |
|||
options?: { [key: string]: any }, |
|||
) { |
|||
return request<API.RVoid>('/api/citrus/register/sendCode', { |
|||
method: 'POST', |
|||
params: { |
|||
...params, |
|||
}, |
|||
...(options || {}), |
|||
}); |
|||
} |
|||
|
|||
/** 此处后端没有提供注释 POST /api/citrus/register/submitRegister */ |
|||
export async function submitRegister(body: API.RegisterBo, options?: { [key: string]: any }) { |
|||
return request<API.RVoid>('/api/citrus/register/submitRegister', { |
|||
method: 'POST', |
|||
headers: { |
|||
'Content-Type': 'application/json', |
|||
}, |
|||
data: body, |
|||
...(options || {}), |
|||
}); |
|||
} |
@ -0,0 +1,21 @@ |
|||
import SparkMD5 from 'spark-md5'; |
|||
|
|||
async function toMD5(file: File): Promise<string> { |
|||
return new Promise((resolve, reject) => { |
|||
const spark = new SparkMD5.ArrayBuffer(); |
|||
const fileReader = new FileReader(); |
|||
|
|||
fileReader.onload = (e) => { |
|||
spark.append(e.target?.result as ArrayBuffer); |
|||
resolve(spark.end()); |
|||
}; |
|||
|
|||
fileReader.onerror = (err) => { |
|||
reject(err); |
|||
}; |
|||
|
|||
fileReader.readAsArrayBuffer(file); |
|||
}); |
|||
} |
|||
|
|||
export { toMD5 }; |
Loading…
Reference in new issue