一、图例
二、概述
Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但本示例中的服务端无法实时了解用户上传了多少文件,上传了什么文件。如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。
三、服务端签名直传并设置上传回调
(1)图例
当用户要上传一个文件到OSS,而且希望将上传的结果返回给应用服务器时,需要设置一个回调函数,将请求告知应用服务器。用户上传完文件后,不会直接得到返回结果,而是先通知应用服务器,再把结果转达给用户。
(2)具体步骤
1、用户向应用服务器请求上传Policy和回调
/** @name 获取上传签名 */
getSignature = async (path: string) => {
const cache = UploadService.cache.get(path);
if (cache) return cache;
const signature = await this.request<OssSignature>(
`${this.basePath}/signature`,
{
method: 'GET',
body: { path },
},
);
const expired = parseInt(signature.expire) * 1000;
UploadService.cache.set(path, signature, expired);
return signature;
};
2、应用服务器返回上传Policy和回调设置代码
- accessid:用户请求的accessid。
- host:用户要往哪个域名发送上传请求。
- policy:用户表单上传的策略(Policy),是经过Base64编码过的字符串。
- signature:对Policy签名后的字符串。
- expire:上传策略Policy失效时间,在服务端指定。失效时间之前都可以利用此Policy上传文件,无需每次上传都去服务端获取签名
3、使用第2步获取到的数据,用户直接向OSS发送文件上传请求
/** @name 上传到OSS */
upload = async (
file: File,
path: string,
observe?: (ob: FetchObserver) => void,
signal?: AbortSignal,
) => {
path = normalizePath(path);
const ext = getExt(file.name);
//获取签名
const signature = await this.getSignature(path);
const formData = new FormData();
const key = path + uuid() + (ext && '.') + ext;
formData.append('key', key);
formData.append('policy', signature.policy);
formData.append('OSSAccessKeyId', signature.accessid);
formData.append('success_action_status', '200');
formData.append('signature', signature.signature);
formData.append('callback', signature.callback);
formData.append('file', file);
const { Status, message } = await this.request<{
Status: string;
message: string;
}>(signature.host, {
method: 'POST',
body: formData,
signal,
observe,
});
if (Status !== 'OK') {
throw new Error(message);
}
return key;
};
(1)key:文件的OSS路径
(2)file:上传的文件
4、OSS根据用户的回调设置,发送回调请求给应用服务器
5、应用服务器返回响应给OSS
6、OSS将应用服务器返回的消息返回给用户
四、关于上传回调错误参考
五、参考文档
https://help.aliyun.com/document_detail/31927.html