本方案实现了阿里云OSS直传功能,支持:
接口地址:POST /oss/direct/signature
请求参数:
dir(可选):上传目录,默认 video/fileName(可选):文件名,不传则自动生成UUIDmaxSize(可选):最大文件大小(字节),默认100MBexpireTime(可选):过期时间(毫秒),默认1小时响应示例:
{
"code": 200,
"success": true,
"data": {
"accessKeyId": "LTAI5t...",
"policy": "eyJleHBpcmF0aW9uIjoi...",
"signature": "abc123...",
"dir": "video/",
"host": "https://alien-volume.oss-cn-beijing.aliyuncs.com",
"expire": "1704067200",
"ossKey": "video/uuid-filename.mp4",
"callbackUrl": "",
"callbackBody": ""
}
}
接口地址:POST /oss/direct/multipart/init
请求参数:
ossKey(必需):OSS文件路径,如 video/filename.mp4响应示例:
{
"code": 200,
"success": true,
"data": {
"uploadId": "abc123...",
"ossKey": "video/filename.mp4"
}
}
接口地址:POST /oss/direct/multipart/upload
请求参数:
ossKey(必需):OSS文件路径uploadId(必需):上传IDpartNumber(必需):分片序号(从1开始)partData(必需):分片数据(二进制)响应示例:
{
"code": 200,
"success": true,
"data": {
"partNumber": 1,
"eTag": "\"abc123...\""
}
}
接口地址:POST /oss/direct/multipart/complete
请求参数:
ossKey(必需):OSS文件路径uploadId(必需):上传IDpartETags(必需):所有分片的ETag列表(JSON数组)请求Body示例:
[
{"partNumber": 1, "eTag": "\"abc123...\""},
{"partNumber": 2, "eTag": "\"def456...\""},
{"partNumber": 3, "eTag": "\"ghi789...\""}
]
响应示例:
{
"code": 200,
"success": true,
"data": {
"fileUrl": "https://alien-volume.oss-cn-beijing.aliyuncs.com/video/filename.mp4",
"ossKey": "video/filename.mp4"
}
}
接口地址:POST /oss/direct/multipart/abort
请求参数:
ossKey(必需):OSS文件路径uploadId(必需):上传ID接口地址:GET /oss/direct/multipart/list
请求参数:
ossKey(必需):OSS文件路径uploadId(必需):上传ID响应示例:
{
"code": 200,
"success": true,
"data": [
{
"partNumber": 1,
"eTag": "\"abc123...\"",
"size": 5242880
},
{
"partNumber": 2,
"eTag": "\"def456...\"",
"size": 5242880
}
]
}
接口地址:POST /oss/direct/callback
请求头:
Authorization:OSS回调的Authorization头请求参数:
pubKeyUrl:公钥URLcallbackBody:回调Body(JSON格式)/oss/direct/signature 获取签名/oss/direct/multipart/init 初始化分片上传,获取 uploadId/oss/direct/multipart/upload 上传/oss/direct/multipart/complete 合并分片/oss/direct/multipart/list 查询已上传的分片/oss/direct/multipart/complete 合并// 1. 获取签名
const response = await fetch('/oss/direct/signature?dir=video/&fileName=test.mp4', {
method: 'POST'
});
const { data } = await response.json();
// 2. 构建FormData
const formData = new FormData();
formData.append('key', data.ossKey);
formData.append('policy', data.policy);
formData.append('OSSAccessKeyId', data.accessKeyId);
formData.append('signature', data.signature);
formData.append('file', file); // 文件对象
// 3. 直接上传到OSS
const uploadResponse = await fetch(data.host, {
method: 'POST',
body: formData
});
// 4. 上传成功,获取文件URL
const fileUrl = data.host + '/' + data.ossKey;
// 1. 初始化分片上传
const initResponse = await fetch('/oss/direct/multipart/init', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ossKey=video/test.mp4`
});
const { data: initData } = await initResponse.json();
const { uploadId, ossKey } = initData;
// 2. 分片上传
const chunkSize = 5 * 1024 * 1024; // 5MB
const chunks = Math.ceil(file.size / chunkSize);
const partETags = [];
for (let i = 0; i < chunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
const chunkResponse = await fetch('/oss/direct/multipart/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
ossKey,
uploadId,
partNumber: i + 1,
partData: await chunk.arrayBuffer()
})
});
const { data: partData } = await chunkResponse.json();
partETags.push({
partNumber: partData.partNumber,
eTag: partData.eTag
});
}
// 3. 完成分片上传
const completeResponse = await fetch('/oss/direct/multipart/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
ossKey,
uploadId,
partETags
})
});
const { data: completeData } = await completeResponse.json();
const fileUrl = completeData.fileUrl;
/oss/direct/multipart/abort 清理未完成的分片确保在 application.yml 或 Nacos 中配置了以下OSS参数:
ali:
oss:
accessKeyId: your-access-key-id
accessKeySecret: your-access-key-secret
endPoint: oss-cn-beijing.aliyuncs.com
bucketName: your-bucket-name