Ich versuche, eine Datei in meinen AWS-Bucket mithilfe des mehrteiligen AWS-Uploads hochzuladen. Dies funktioniert gut für kleinere Dateien, aber jetzt versuche ich, eine große Datei hinzuzufügen (die in 170 Teile geteilt wird), und ich erhalte die folgenden Fehler:AWS Multipart-Upload-Knoten js-Fehler
multiErr, upload part error: { [RequestTimeTooSkewed: The difference between the request time and the current time is too large.]
ODER diesen Fehler:
multiErr, upload part error: { [TimeoutError: Connection timed out after 120000ms]
Irgendeine Idee, wie das behoben werden kann? Hier ist mein Code:
var fs = require('fs');
var AWS = require('aws-sdk');
AWS.config.loadFromPath('./config.json')
var s3 = new AWS.S3();
// File
var fileName = 'atom.mov';
var filePath = './' + fileName;
var fileKey = fileName;
var buffer = fs.readFileSync('./' + filePath);
// S3 Upload options
var bucket = 'test.bucket.1234';
// Upload
var startTime = new Date();
var partNum = 0;
var partSize = 1024 * 1024 * 5; // Minimum 5MB per chunk (except the last part) http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadComplete.html
var numPartsLeft = Math.ceil(buffer.length/partSize);
var maxUploadTries = 3;
var multiPartParams = {
Bucket: bucket,
Key: fileKey,
ContentType: 'application/mov'
};
var multipartMap = {
Parts: []
};
function completeMultipartUpload(s3, doneParams) {
s3.completeMultipartUpload(doneParams, function(err, data) {
if (err) {
console.log("An error occurred while completing the multipart upload");
console.log(err);
} else {
var delta = (new Date() - startTime)/1000;
console.log('Completed upload in', delta, 'seconds');
console.log('Final upload data:', data);
}
});
}
function uploadPart(s3, multipart, partParams, tryNum) {
var tryNum = tryNum || 1;
s3.uploadPart(partParams, function(multiErr, mData) {
if (multiErr){
console.log('multiErr, upload part error:', multiErr);
if (tryNum < maxUploadTries) {
console.log('Retrying upload of part: #', partParams.PartNumber)
uploadPart(s3, multipart, partParams, tryNum + 1);
} else {
console.log('Failed uploading part: #', partParams.PartNumber)
}
return;
}
.Parts[this.request.params.PartNumber - 1] = {
ETag: mData.ETag,
PartNumber: Number(this.request.params.PartNumber)
};
console.log("Completed part", this.request.params.PartNumber);
console.log('mData', mData);
if (--numPartsLeft > 0) return; // complete only when all parts uploaded
var doneParams = {
Bucket: bucket,
Key: fileKey,
MultipartUpload: multipartMap,
UploadId: multipart.UploadId
};
console.log("Completing upload...");
completeMultipartUpload(s3, doneParams);
});
}
// Multipart
console.log("Creating multipart upload for:", fileKey);
s3.createMultipartUpload(multiPartParams, function(mpErr, multipart){
if (mpErr) { console.log('Error!', mpErr); return; }
console.log("Got upload ID", multipart.UploadId);
// Grab each partSize chunk and upload it as a part
for (var rangeStart = 0; rangeStart < buffer.length; rangeStart += partSize) {
partNum++;
var end = Math.min(rangeStart + partSize, buffer.length),
partParams = {
Body: buffer.slice(rangeStart, end),
Bucket: bucket,
Key: fileKey,
PartNumber: String(partNum),
UploadId: multipart.UploadId
};
// Send a single part
console.log('Uploading part: #', partParams.PartNumber, ', Range start:', rangeStart);
uploadPart(s3, multipart, partParams);
}
});
Timeouts sind eine Sache. Sie passieren. Aber es sieht so aus, als müssten Sie die Anfragen erneut signieren, bevor Sie sie erneut versuchen, wenn eine Zeitüberschreitung auftritt - anderenfalls ist das Datum in der Anfrage zu alt, was "RequestTimeTooSkewed" bedeutet. –
Hmm, okay, wie kann ich die Anfragen neu signieren, bevor ich sie erneut versuche? – deeveeABC
Eigentlich, wenn ich den Code näher betrachte, denke ich, dass das schon für dich passiert. Das Problem ist, dass Sie alle 170 Teile in schneller Folge starten, was zu 170 simultanen Verbindungen führt, was potentiell zu viel ist. Dies würde zu Timeouts führen und indirekt zu Verzögerungen bei Anfragen aufgrund der lokalen Ressourcen- (CPU-, Netzwerk-) Sättigung. Ich löste dies, als ich einen asynchronen parallelen MultipartUploader (nicht in js) schrieb, indem ich ein Array aller benötigten Teilenummern und Bereiche speicherte, die ersten "n" Teile (einen konfigurierbaren Wert) in einer Schleife und dann jedes Mal den callback fire ... –