重点:headers要保持一致!如果生成签名URL时设置了header参数,例如用户元数据,存储类型等,则调用签名URL上传文件时,也需要将这些参数发送至服务端。如果签名和发送至服务端的不一致,会报签名错误。
错误信息
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<EC>0002-00000040</EC>
<RecommendDoc>https://api.aliyun.com/troubleshoot?q=0002-00000040</RecommendDoc>
</Error>
Java服务端生成签名URL
public String uploadId(String path) {
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(properties.getBucket(), path);
InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
return result.getUploadId();
}
public String generatePartUploadPreSignUrl(String filename, String partNumber, String uploadId) {
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(properties.getBucket(), filename, HttpMethod.PUT);
request.setMethod(HttpMethod.PUT);
// 一个小时有效期
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
request.setExpiration(expiration);
// 分块索引
request.addQueryParameter("partNumber", partNumber);
request.addQueryParameter("uploadId", uploadId);
// 如果生成签名URL时设置了header参数,例如用户元数据,存储类型等,则调用签名URL上传文件时,也需要将这些参数发送至服务端。如果签名和发送至服务端的不一致,会报签名错误。
Map<String, String> headers = new HashMap<>();
headers.put(OSSHeaders.CONTENT_TYPE, "multipart/form-data");
request.setHeaders(headers);
return client.generatePresignedUrl(request).toString();
}
前端使用签名URL上传
// 获取上传alioss的签名
aliossPreSignUrl(this.uploadId, this.filename, this.chunkIndex)
.then((res: any) => {
// 拿到签名之后将分块内容上传到alioss
return this.client.put(res.data.url, tmpFile, {
// 如果生成签名URL时设置了header参数,例如用户元数据,存储类型等,则调用签名URL上传文件时,也需要将这些参数发送至服务端。如果签名和发送至服务端的不一致,会报签名错误。
headers: {
"Content-Type": "multipart/form-data",
},
});
})
.then(() => {
this.chunkIndex += 1;
this.start();
})
.catch((e: any) => {
this.uploadedFail(e);
});