I am building an application using Angular2. I am trying to do a Multipart upload to Amazon S3. I need to show a 'Success' or a 'Failed' toaster based on successfully uploading/failing an object. I have 'promises' involved in my code. But the Success toaster is being shown, even before the promise is completed. I am not sure what is going wrong here. Can someone please help me here.
This is the caller:
this.multipartupload(params).then((data) => {
var fileNameArr = params.Key.split('/')
this.uiService.showMessage('success', fileNameArr[fileNameArr.length - 1] + ' Uploaded');
}).catch((err) => {
this.uiService.showMessage('warning', err.message);
})
Multipart upload works in three different stages: Create, Upload and Complete. I want to show the success message only after the 'Complete' stage is completed. Below is the code code for ' multipartUpload
', which is called from the above code:
multipartupload(params: any){
var s3 = this.getS3();
var multipartParams = {
Bucket: params.Bucket,
Key: params.Key,
ServerSideEncryption: params.ServerSideEncryption
}
var partSize = 5 * 1024 * 1024;
var partNum = 0;
var multipartMap = {
Parts: []
};
var numPartsLeft = Math.ceil(params.Body.size / partSize);
return s3.createMultipartUpload(multipartParams).promise()
.then((data) => {
for(var rangeStart = 0; rangeStart < params.Body.size; rangeStart += partSize){
var end = Math.min(rangeStart + partSize, params.Body.size);
partNum++;
var partParams = {
Body: params.Body.slice(rangeStart, end),
Bucket: params.Bucket,
Key: params.Key,
PartNumber: String(partNum),
UploadId: data.UploadId
}
return uploadPart(s3, data, partParams); // -> the toastr is shown at this point. I want it to wait till all the parts are uploaded.
}
})
.catch((err) => {
return err;
})
function uploadPart(s3, multipart, partParams, tryNum = 0){
var tryNum = tryNum | 1;
s3.uploadPart(partParams).promise()
.then(
(mData) => {
multipartMap.Parts[partParams.PartNumber - 1] = {
ETag: mData.ETag,
PartNumber: Number(partParams.PartNumber)
};
if (--numPartsLeft > 0) return;
var doneParams = {
Bucket: params.Bucket,
Key: params.Key,
MultipartUpload: multipartMap,
UploadId: multipart.UploadId
};
return s3.completeMultipartUpload(doneParams).promise().then((data) =>{
return data;
})
.catch((err) => {
return err;
})
})
.catch((multiErr) => {
if(tryNum < 3){
uploadPart(s3, multipart, partParams, tryNum + 1);
}
return multiErr;
})
}
}
I understand that this code is a little long. But I wanted to convey the whole context. Thanks for understanding. I would appreciate if someone can share on how to wait till the last part is uploaded successfully.
It would appear that you are missing :
for
loop Here it is with a bit of additional tidying ...
this.multipartupload(params)
.then((data) => {
var fileNameArr = params.Key.split('/');
this.uiService.showMessage('success', fileNameArr[fileNameArr.length - 1] + ' Uploaded');
}).catch((err) => {
this.uiService.showMessage('warning', err.message);
});
multipartupload(params: any) {
var s3 = this.getS3(),
partSize = 5 * 1024 * 1024,
partNum = 0,
multipartMap = { Parts: [] };
var numPartsLeft = Math.ceil(params.Body.length / partSize);
return s3.createMultipartUpload({
Bucket: params.Bucket,
Key: params.Key,
ServerSideEncryption: params.ServerSideEncryption
}).promise()
.then((data) => {
var promises = []; // <<<<<<< create an array of promises
for(var rangeStart = 0; rangeStart < params.Body.length; rangeStart += partSize) {
promises.push(uploadPart(s3, data, {
Body: params.Body.slice(rangeStart, Math.min(rangeStart + partSize, params.Body.length)),
Bucket: params.Bucket,
Key: params.Key,
PartNumber: String(++partNum),
UploadId: data.UploadId
}, 1));
}
return Promise.all(promises) // <<<<<<< return a single aggregated promise.
.then((results => results.filter(res => res !== null))); // filter out any nulls delivered by the (--numPartsLeft > 0) condition below.
});
function uploadPart(s3, multipart, partParams, tryNum) {
return s3.uploadPart(partParams).promise()
// ^^^^^^
.then((mData) => {
multipartMap.Parts[partParams.PartNumber - 1] = {
ETag: mData.ETag,
PartNumber: Number(partParams.PartNumber)
};
if (--numPartsLeft > 0) {
return null;
}
return s3.completeMultipartUpload({
Bucket: params.Bucket,
Key: params.Key,
MultipartUpload: multipartMap,
UploadId: multipart.UploadId
}).promise();
}).catch((multiErr) => (tryNum < 3) ? uploadPart(s3, multipart, partParams, tryNum + 1) : multiErr); // note the implicit return here.
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.