【问题标题】:AWS Multipart upload node js errorsAWS Multipart 上传节点 js 错误
【发布时间】:2017-01-22 04:37:43
【问题描述】:

我正在尝试使用 AWS 分段上传将文件上传到我的 AWS 存储桶。这适用于较小的文件,但是现在我尝试添加一个大文件(分为 170 个部分),我收到以下错误:

multiErr, upload part error: { [RequestTimeTooSkewed: The difference between the request time and the current time is too large.]

或者这个错误:

multiErr, upload part error: { [TimeoutError: Connection timed out after 120000ms]

知道如何解决这个问题吗?这是我的代码:

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);
  }
});

【问题讨论】:

  • 超时是一回事。他们发生了。但是看起来你需要在重试请求之前重新签署请求,当发生超时时——否则请求中的日期将太陈旧,这就是RequestTimeTooSkewed 的意思。
  • 嗯好吧,我如何在重试之前重新签署请求?
  • 实际上,更仔细地查看代码,我认为这已经发生在你身上。问题是您快速连续启动所有 170 个部分,导致 170 个同时连接,这可能太多了。这将导致超时并间接导致由于本地资源(CPU、网络)饱和而导致请求延迟。我在编写异步并行多部分上传器(不在 js 中)时解决了这个问题,方法是存储所有需要的部分编号和范围的数组,在循环中开始第一个“n”部分(可配置值),然后每次回调触发...
  • ...在任何一个部分成功上传后,我从数组中弹出下一个成员并开始上传下一个部分,直到全部成功上传...所以我一直没有更多比同时运行的“n”个部分。在 100 Mbit/秒的连接上,我发现 8 到 16 个同时上传是最佳的最佳连接点。那有意义吗?这将解释为什么较小的文件可以正常工作,但大文件会失败。
  • 是的,这是有道理的。谢谢。我将在下周尝试实施

标签: javascript node.js amazon-web-services amazon-s3 timeout


【解决方案1】:

s3.upload 的默认超时时间为 120000 毫秒(两分钟)。上传大文件或连接不佳时,您可能需要增加它。

使用 S3 构造函数设置默认超时。

 const s3 = new AWS.S3({
     httpOptions : {
        timeout: 300000 
     }
     //... other config
 });

看看S3 documentation

【讨论】:

    【解决方案2】:

    尝试在您的配置中设置 timeout 属性。 这适用于我 500MB 以上的文件,30 分钟可能有点过大,但它有效;)

    var aws = require('aws-sdk');
    
    aws.config.update({
        region: "your region",
        accessKeyId: "your access key",
        secretAccessKey: "your secret",
        httpOptions: {"timeout: 1800000"}
    });
    

    【讨论】:

      猜你喜欢
      • 2020-02-12
      • 2020-05-29
      • 2020-10-20
      • 2022-11-12
      • 1970-01-01
      • 2014-12-19
      • 2014-10-05
      • 2017-11-21
      • 2019-06-19
      相关资源
      最近更新 更多