s3.abortMultipartUpload error: Access denied
s3.abortMultipartUpload error: Access denied
我正在尝试建立一个上传机制来在 S3 上上传大文件,如果我愿意,也可以中止该过程。
下面是我上传文件的前端代码
html
<input type="file" id="multipartInput">
<button id="multipartInputBtn">send file</button>
JavaScript
document.getElementById('multipartInputBtn').addEventListener('click', async () => {
const multipartInput_fileInput = document.getElementById('multipartInput');
const file = multipartInput_fileInput.files[0];
const fileName = file.name;
const fileSize = file.size;
const url = `https://uniquestring.execute-api.ap-south-1.amazonaws.com/dev`;
try {
let res = await axios.post(`${url}/getUploadId`, { fileName: fileName });
const uploadId = res.data.uploadId;
console.log(res);
console.log('Inside uploadMultipartFile');
const chunkSize = 100 * 1024 * 1024; // 100MiB
const chunkCount = Math.floor(fileSize / chunkSize) + 1;
console.log(`chunkCount: ${chunkCount}`);
let multiUploadArray = [];
for (let uploadCount = 1; uploadCount < chunkCount + 1; uploadCount++) {
let start = (uploadCount - 1) * chunkSize;
let end = uploadCount * chunkSize;
let fileBlob = uploadCount < chunkCount ? file.slice(start, end) : file.slice(start);
let getSignedUrlRes = await axios.post(`${url}/getUploadPart`, {
fileName: fileName,
partNumber: uploadCount,
uploadId: uploadId
});
let uploadChunck = await fetch(preSignedUrl, {
method: 'PUT',
body: fileBlob
});
console.log(uploadChunck);
console.log(`preSignedUrl ${uploadCount} : ${preSignedUrl}`);
console.log(fileBlob);
// Start sending files to S3 part by part
let uploadChunck = await axios.put(presignedUrl, fileBlob)
console.log(uploadChunck)
}
} catch (err) {
console.log(err, err.stack);
}
});
使用这种方法我可以上传文件,但是根据文档我尝试实现 abort multiPart Upload 我相应地实现了我的前端逻辑
前端
<button id="abortUploadBtn">Abort Upload</button>
document.getElementById('abortUploadBtn').addEventListener('click', () => {
const multipartInput_fileInput = document.getElementById('multipartInput');
const file = multipartInput_fileInput.files[0];
const fileName = file.name;
const uploadId = sessionStorage.getItem('uploadId');
const url = `https://68qb5fre0e.execute-api.ap-south-1.amazonaws.com/dev`;
console.log({ fileName: fileName, uploadId: uploadId });
axios
.post(`${url}/abortUpload`, { fileName: fileName, uploadId: uploadId })
.then((r) => console.log(r))
.catch((err) => console.error(err));
});
Lambda 后端
const AWS = require('aws-sdk');
const s3 = new AWS.S3({ signatureVersion: 'v4', region: 'ap-south-1' });
exports.handler = async (event) => {
const body = JSON.parse(event.body);
try {
let params = {
Bucket: process.env.bucketName,
Key: body.fileName,
UploadId: body.uploadId
};
const completeUpload = await s3.abortMultipartUpload(params).promise();
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify({ completeUpload: completeUpload })
};
} catch (err) {
console.log(err);
return {
statusCode: 500,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify({ error: err, details: err.stack })
};
}
};
导致我出现此 cloudwatch 错误
2021-03-11T11:51:43.367Z 58cba880-bbc2-4522-8c0f-8c73b2d3cd8f INFO AccessDenied: Access Denied
at Request.extractError (/var/task/node_modules/aws-sdk/lib/services/s3.js:712:35)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:688:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:690:12)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
code: 'AccessDenied',
region: null,
time: 2021-03-11T11:51:43.363Z,
requestId: 'BBF9AC13DD0C54FA',
extendedRequestId: '/aQMS0mNmAEimuZ8nL0p+iDY9ndePTHU5fsfsnlbOH+anaWB4BOZH2bvVbn4wXefimH7gOh5za3U=',
cfId: undefined,
statusCode: 403,
retryable: false,
retryDelay: 5.35506042250955
}
但具有讽刺意味的是,如果我尝试在我的 PC 上本地严格使用文档中建议的方法(如下所述),它绝对可以正常工作
var params = {
Bucket: "examplebucket",
Key: "bigobject",
UploadId: "xadcOB_7YPBOJuoFiQ9cz4P3Pe6FIZwO4f7wN93uHsNBEw97pl5eNwzExg0LAT2dUN91cOmrEQHDsP3WA60CEg--"
};
s3.abortMultipartUpload(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
data = {
}
*/
});
结果
{}
我应该怎么做才能完成这项工作?
编辑
我已附上我的 serverless.yml
以突出显示权限
provider:
name: aws
runtime: nodejs14.x
lambdaHashingVersion: 20201221
stage: dev
region: ap-south-1
apiGateway:
shouldStartNameWithService: true
iam:
role:
statements:
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
Resource: "arn:aws:s3:::${self:custom.bucketName}/*"
environment:
bucketName: ${self:custom.bucketName}
provider:
name: aws
runtime: nodejs14.x
lambdaHashingVersion: 20201221
stage: dev
region: ap-south-1
apiGateway:
shouldStartNameWithService: true
iam:
role:
statements:
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:AbortMultipartUpload"
Resource: "arn:aws:s3:::${self:custom.bucketName}/*"
environment:
bucketName: ${self:custom.bucketName}
你需要AbortMultipartUpload权限,我已经修改了上面模板中的调用。
我正在尝试建立一个上传机制来在 S3 上上传大文件,如果我愿意,也可以中止该过程。 下面是我上传文件的前端代码
html
<input type="file" id="multipartInput">
<button id="multipartInputBtn">send file</button>
JavaScript
document.getElementById('multipartInputBtn').addEventListener('click', async () => {
const multipartInput_fileInput = document.getElementById('multipartInput');
const file = multipartInput_fileInput.files[0];
const fileName = file.name;
const fileSize = file.size;
const url = `https://uniquestring.execute-api.ap-south-1.amazonaws.com/dev`;
try {
let res = await axios.post(`${url}/getUploadId`, { fileName: fileName });
const uploadId = res.data.uploadId;
console.log(res);
console.log('Inside uploadMultipartFile');
const chunkSize = 100 * 1024 * 1024; // 100MiB
const chunkCount = Math.floor(fileSize / chunkSize) + 1;
console.log(`chunkCount: ${chunkCount}`);
let multiUploadArray = [];
for (let uploadCount = 1; uploadCount < chunkCount + 1; uploadCount++) {
let start = (uploadCount - 1) * chunkSize;
let end = uploadCount * chunkSize;
let fileBlob = uploadCount < chunkCount ? file.slice(start, end) : file.slice(start);
let getSignedUrlRes = await axios.post(`${url}/getUploadPart`, {
fileName: fileName,
partNumber: uploadCount,
uploadId: uploadId
});
let uploadChunck = await fetch(preSignedUrl, {
method: 'PUT',
body: fileBlob
});
console.log(uploadChunck);
console.log(`preSignedUrl ${uploadCount} : ${preSignedUrl}`);
console.log(fileBlob);
// Start sending files to S3 part by part
let uploadChunck = await axios.put(presignedUrl, fileBlob)
console.log(uploadChunck)
}
} catch (err) {
console.log(err, err.stack);
}
});
使用这种方法我可以上传文件,但是根据文档我尝试实现 abort multiPart Upload 我相应地实现了我的前端逻辑
前端
<button id="abortUploadBtn">Abort Upload</button>
document.getElementById('abortUploadBtn').addEventListener('click', () => {
const multipartInput_fileInput = document.getElementById('multipartInput');
const file = multipartInput_fileInput.files[0];
const fileName = file.name;
const uploadId = sessionStorage.getItem('uploadId');
const url = `https://68qb5fre0e.execute-api.ap-south-1.amazonaws.com/dev`;
console.log({ fileName: fileName, uploadId: uploadId });
axios
.post(`${url}/abortUpload`, { fileName: fileName, uploadId: uploadId })
.then((r) => console.log(r))
.catch((err) => console.error(err));
});
Lambda 后端
const AWS = require('aws-sdk');
const s3 = new AWS.S3({ signatureVersion: 'v4', region: 'ap-south-1' });
exports.handler = async (event) => {
const body = JSON.parse(event.body);
try {
let params = {
Bucket: process.env.bucketName,
Key: body.fileName,
UploadId: body.uploadId
};
const completeUpload = await s3.abortMultipartUpload(params).promise();
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify({ completeUpload: completeUpload })
};
} catch (err) {
console.log(err);
return {
statusCode: 500,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify({ error: err, details: err.stack })
};
}
};
导致我出现此 cloudwatch 错误
2021-03-11T11:51:43.367Z 58cba880-bbc2-4522-8c0f-8c73b2d3cd8f INFO AccessDenied: Access Denied
at Request.extractError (/var/task/node_modules/aws-sdk/lib/services/s3.js:712:35)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:688:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:690:12)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
code: 'AccessDenied',
region: null,
time: 2021-03-11T11:51:43.363Z,
requestId: 'BBF9AC13DD0C54FA',
extendedRequestId: '/aQMS0mNmAEimuZ8nL0p+iDY9ndePTHU5fsfsnlbOH+anaWB4BOZH2bvVbn4wXefimH7gOh5za3U=',
cfId: undefined,
statusCode: 403,
retryable: false,
retryDelay: 5.35506042250955
}
但具有讽刺意味的是,如果我尝试在我的 PC 上本地严格使用文档中建议的方法(如下所述),它绝对可以正常工作
var params = {
Bucket: "examplebucket",
Key: "bigobject",
UploadId: "xadcOB_7YPBOJuoFiQ9cz4P3Pe6FIZwO4f7wN93uHsNBEw97pl5eNwzExg0LAT2dUN91cOmrEQHDsP3WA60CEg--"
};
s3.abortMultipartUpload(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
data = {
}
*/
});
结果
{}
我应该怎么做才能完成这项工作?
编辑
我已附上我的 serverless.yml
以突出显示权限
provider:
name: aws
runtime: nodejs14.x
lambdaHashingVersion: 20201221
stage: dev
region: ap-south-1
apiGateway:
shouldStartNameWithService: true
iam:
role:
statements:
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
Resource: "arn:aws:s3:::${self:custom.bucketName}/*"
environment:
bucketName: ${self:custom.bucketName}
provider:
name: aws
runtime: nodejs14.x
lambdaHashingVersion: 20201221
stage: dev
region: ap-south-1
apiGateway:
shouldStartNameWithService: true
iam:
role:
statements:
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:AbortMultipartUpload"
Resource: "arn:aws:s3:::${self:custom.bucketName}/*"
environment:
bucketName: ${self:custom.bucketName}
你需要AbortMultipartUpload权限,我已经修改了上面模板中的调用。