问题 使用节点js中的AWS sdk将整个目录树上载到S3


我目前使用如下方式将单个对象上传到S3:

var options = {
        Bucket: bucket,
        Key: s3Path,
        Body: body,
        ACL: s3FilePermissions
};

S3.putObject(options,
function (err, data) {
    //console.log(data);
});

但是当我有一个大型资源文件夹时,我使用了 AWS CLI 工具。
我想知道,是否有一种原生方式与aws sdk做同样的事情(将整个文件夹上传到s3)?


7649
2017-12-27 18:08


起源



答案:


老派递归的方式我匆匆忙忙地掀起。仅使用核心节点模块和标准AWS sdk。

var AWS = require('aws-sdk');
var path = require("path");
var fs = require('fs');

const uploadDir = function(s3Path, bucketName) {

    let s3 = new AWS.S3();

    function walkSync(currentDirPath, callback) {
        fs.readdirSync(currentDirPath).forEach(function (name) {
            var filePath = path.join(currentDirPath, name);
            var stat = fs.statSync(filePath);
            if (stat.isFile()) {
                callback(filePath, stat);
            } else if (stat.isDirectory()) {
                walkSync(filePath, callback);
            }
        });
    }

    walkSync(s3Path, function(filePath, stat) {
        let bucketPath = filePath.substring(s3Path.length+1);
        let params = {Bucket: bucketName, Key: bucketPath, Body: fs.readFileSync(filePath) };
        s3.putObject(params, function(err, data) {
            if (err) {
                console.log(err)
            } else {
                console.log('Successfully uploaded '+ bucketPath +' to ' + bucketName);
            }
        });

    });
};

uploadDir("path to your folder", "your bucket name");

特别感谢Ali来自 这个帖子 帮助获取文件名


6
2017-09-14 07:52





前几天我只是在考虑这个问题,并且正在考虑这样的事情:

...    
var async = require('async'),
    fs = require('fs'),
    path = require("path");

var directoryName = './test',
    directoryPath = path.resolve(directoryName);

var files = fs.readdirSync(directoryPath);
async.map(files, function (f, cb) {
    var filePath = path.join(directoryPath, f);

    var options = {
        Bucket: bucket,
        Key: s3Path,
        Body: fs.readFileSync(filePath),
        ACL: s3FilePermissions
    };

    S3.putObject(options, cb);

}, function (err, results) {
    if (err) console.error(err);
    console.log(results);
});

3
2018-01-28 20:37



fs.readFileSync(filePath) 这条线让我回报 Error: EISDIR: illegal operation on a directory, read 像这儿: stackoverflow.com/questions/25883775/... - Barlas Apaydin


答案:


老派递归的方式我匆匆忙忙地掀起。仅使用核心节点模块和标准AWS sdk。

var AWS = require('aws-sdk');
var path = require("path");
var fs = require('fs');

const uploadDir = function(s3Path, bucketName) {

    let s3 = new AWS.S3();

    function walkSync(currentDirPath, callback) {
        fs.readdirSync(currentDirPath).forEach(function (name) {
            var filePath = path.join(currentDirPath, name);
            var stat = fs.statSync(filePath);
            if (stat.isFile()) {
                callback(filePath, stat);
            } else if (stat.isDirectory()) {
                walkSync(filePath, callback);
            }
        });
    }

    walkSync(s3Path, function(filePath, stat) {
        let bucketPath = filePath.substring(s3Path.length+1);
        let params = {Bucket: bucketName, Key: bucketPath, Body: fs.readFileSync(filePath) };
        s3.putObject(params, function(err, data) {
            if (err) {
                console.log(err)
            } else {
                console.log('Successfully uploaded '+ bucketPath +' to ' + bucketName);
            }
        });

    });
};

uploadDir("path to your folder", "your bucket name");

特别感谢Ali来自 这个帖子 帮助获取文件名


6
2017-09-14 07:52





前几天我只是在考虑这个问题,并且正在考虑这样的事情:

...    
var async = require('async'),
    fs = require('fs'),
    path = require("path");

var directoryName = './test',
    directoryPath = path.resolve(directoryName);

var files = fs.readdirSync(directoryPath);
async.map(files, function (f, cb) {
    var filePath = path.join(directoryPath, f);

    var options = {
        Bucket: bucket,
        Key: s3Path,
        Body: fs.readFileSync(filePath),
        ACL: s3FilePermissions
    };

    S3.putObject(options, cb);

}, function (err, results) {
    if (err) console.error(err);
    console.log(results);
});

3
2018-01-28 20:37



fs.readFileSync(filePath) 这条线让我回报 Error: EISDIR: illegal operation on a directory, read 像这儿: stackoverflow.com/questions/25883775/... - Barlas Apaydin


你可以尝试一下 节点S3-客户

更新:在npm上可用 这里

从同步目录到s3 文档

更新:添加了客户端inialization代码。

var client = s3.createClient({
    maxAsyncS3: 20,     // this is the default
    s3RetryCount: 3,    // this is the default
    s3RetryDelay: 1000, // this is the default
    multipartUploadThreshold: 20971520, // this is the default (20 MB)
    multipartUploadSize: 15728640, // this is the default (15 MB)
    s3Options: {
      accessKeyId: "YOUR ACCESS KEY",
      secretAccessKey: "YOUR SECRET ACCESS KEY"
    }
  });

var params = {
  localDir: "some/local/dir",
  deleteRemoved: true, // default false, whether to remove s3 objects
                       // that have no corresponding local file.

  s3Params: {
    Bucket: "s3 bucket name",
    Prefix: "some/remote/dir/",
    // other options supported by putObject, except Body and ContentLength.
    // See: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property
  },
};
var uploader = client.uploadDir(params);
uploader.on('error', function(err) {
  console.error("unable to sync:", err.stack);
});
uploader.on('progress', function() {
  console.log("progress", uploader.progressAmount, uploader.progressTotal);
});
uploader.on('end', function() {
  console.log("done uploading");
});

1
2018-04-22 17:26



这不起作用。它只是依靠进步。没有错误,没有进展。 - Hitesh Joshi
您确定客户端已正确初始化吗?我已经编辑了包含客户端初始化的答案。 - unboundev
是。否则它会显示错误。没有错误,客户端正确初始化但不会发生同步。 - Hitesh Joshi
这是网址 gist.github.com/hiteshjoshi/5226abcb225038d969de - Hitesh Joshi
此库目前似乎不支持上载目录中大于1MB的文件。在支持之前,对于通用目录同步到S3,这不是一个很好的解决方案。除了这个破坏性的问题,它是一个非常好用的库。 - dsw88