有没有办法通过浏览器使用生成的预签名 URL 进行分段上传?
3 回答
通过使用签名版本 4 为每个部分上传创建规范请求,我设法在无服务器架构中实现了这一点。您将在此处找到文档AWS Multipart Upload Via Presign Url
Angular - 多部分 Aws 预签名 URL
例子
https://multipart-aws-presigned.stackblitz.io/
https://stackblitz.com/edit/multipart-aws-presigned?file=src/app/app.component.html
下载后端: https ://www.dropbox.com/s/9tm8w3ujaqbo017/serverless-multipart-aws-presigned.tar.gz?dl=0
要使用预签名的 url 将大文件上传到 S3 存储桶,有必要使用分段上传,基本上将文件分成许多部分,从而允许并行上传。
在这里,我们将留下一个后端和前端的基本示例。
后端(无服务打字稿)
const AWSData = {
accessKeyId: 'Access Key',
secretAccessKey: 'Secret Access Key'
};
有3个端点
端点 1:/start-upload要求 S3 开始分段上传,答案是与将要上传的每个部分关联的 UploadId。
export const start: APIGatewayProxyHandler = async (event, _context) => {
const params = {
Bucket: event.queryStringParameters.bucket, /* Bucket name */
Key: event.queryStringParameters.fileName /* File name */
};
const s3 = new AWS.S3(AWSData);
const res = await s3.createMultipartUpload(params).promise()
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: JSON.stringify({
data: {
uploadId: res.UploadId
}
})
};
}
端点 2:/get-upload-url
为要上传的文件拆分的每个部分创建一个预签名 URL。
export const uploadUrl: APIGatewayProxyHandler = async (event, _context) => {
let params = {
Bucket: event.queryStringParameters.bucket, /* Bucket name */
Key: event.queryStringParameters.fileName, /* File name */
PartNumber: event.queryStringParameters.partNumber, /* Part to create pre-signed url */
UploadId: event.queryStringParameters.uploadId /* UploadId from Endpoint 1 response */
};
const s3 = new AWS.S3(AWSData);
const res = await s3.getSignedUrl('uploadPart', params)
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: JSON.stringify(res)
};
}
端点 3:/complete-upload
上传文件的所有部分后,有必要通知它们已经上传,这将使对象在 S3 中正确组装。
export const completeUpload: APIGatewayProxyHandler = async (event, _context) => {
// Parse the post body
const bodyData = JSON.parse(event.body);
const s3 = new AWS.S3(AWSData);
const params: any = {
Bucket: bodyData.bucket, /* Bucket name */
Key: bodyData.fileName, /* File name */
MultipartUpload: {
Parts: bodyData.parts /* Parts uploaded */
},
UploadId: bodyData.uploadId /* UploadId from Endpoint 1 response */
}
const data = await s3.completeMultipartUpload(params).promise()
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
// 'Access-Control-Allow-Methods': 'OPTIONS,POST',
// 'Access-Control-Allow-Headers': 'Content-Type',
},
body: JSON.stringify(data)
};
}
前端(Angular 9)
该文件分为 10MB 部分
有了文件,请求分段上传到端点 1
使用 UploadId,您可以将文件分成 10MB 的几个部分,并从每个部分中使用 Endpoint 2 获得预签名的 url 上传
将部分转换为 blob 到端点 2 中获得的预签名 url 进行 PUT
当您完成上传每个部分时,您会向 Endpoint 3 发出最后一个请求
在所有这一切的例子中,函数uploadMultipartFile
来自 AWS文档:
对于请求签名,分段上传只是一系列常规请求,你发起分段上传,发送一个或多个请求上传分段,最后完成分段上传。您单独签署每个请求,签署分段上传请求并没有什么特别之处
所以我认为你应该为分段上传的每个部分生成一个预签名的 url :(
你的用例是什么?你不能从你的服务器执行一个脚本,并让 s3 访问这个服务器吗?