Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

s3

andrewrk96.5kMIT4.4.0

high level amazon s3 client. upload and download files and directories

amazon, s3, sync, folder, directory, retry, limit, stream, async, parallel, multipart, size

readme

High Level Amazon S3 Client

Features

  • Automatically retry a configurable number of times when S3 returns an error.
  • Includes logic to make multiple requests when there is a 1000 object limit.
  • Ability to set a limit on the maximum parallelization of S3 requests. Retries get pushed to the end of the paralellization queue.
  • Ability to sync a dir to and from S3.
  • Progress reporting.
  • Supports files of any size (up to S3's maximum 5 TB object size limit).
  • Uploads large files quickly using parallel multipart uploads.
  • Uses heuristics to compute multipart ETags client-side to avoid uploading or downloading files unnecessarily.
  • Automatically provide Content-Type for uploads based on file extension.

See also the companion CLI tool which is meant to be a drop-in replacement for s3cmd: s3-cli.

Synopsis

Create a client

var s3 = require('s3');

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 s3 key",
    secretAccessKey: "your s3 secret",
    // any other options are passed to new AWS.S3()
    // See: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#constructor-property
  },
});

Create a client from existing AWS.S3 object

var s3 = require('s3');
var awsS3Client = new AWS.S3(s3Options);
var options = {
  s3Client: awsS3Client,
  // more options available. See API docs below.
};
var client = s3.createClient(options);

Upload a file to S3

var params = {
  localFile: "some/local/file",

  s3Params: {
    Bucket: "s3 bucket name",
    Key: "some/remote/file",
    // 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.uploadFile(params);
uploader.on('error', function(err) {
  console.error("unable to upload:", err.stack);
});
uploader.on('progress', function() {
  console.log("progress", uploader.progressMd5Amount,
            uploader.progressAmount, uploader.progressTotal);
});
uploader.on('end', function() {
  console.log("done uploading");
});

Download a file from S3

var params = {
  localFile: "some/local/file",

  s3Params: {
    Bucket: "s3 bucket name",
    Key: "some/remote/file",
    // other options supported by getObject
    // See: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property
  },
};
var downloader = client.downloadFile(params);
downloader.on('error', function(err) {
  console.error("unable to download:", err.stack);
});
downloader.on('progress', function() {
  console.log("progress", downloader.progressAmount, downloader.progressTotal);
});
downloader.on('end', function() {
  console.log("done downloading");
});

Sync a directory to S3

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

Tips

  • Consider increasing the socket pool size in the http and https global agents. This will improve bandwidth when using uploadDir and downloadDir functions. For example:

    http.globalAgent.maxSockets = https.globalAgent.maxSockets = 20;

API Documentation

s3.AWS

This contains a reference to the aws-sdk module. It is a valid use case to use both this module and the lower level aws-sdk module in tandem.

s3.createClient(options)

Creates an S3 client.

options:

  • s3Client - optional, an instance of AWS.S3. Leave blank if you provide s3Options.
  • s3Options - optional. leave blank if you provide s3Client.
  • maxAsyncS3 - maximum number of simultaneous requests this client will ever have open to S3. defaults to 20.
  • s3RetryCount - how many times to try an S3 operation before giving up. Default 3.
  • s3RetryDelay - how many milliseconds to wait before retrying an S3 operation. Default 1000.
  • multipartUploadThreshold - if a file is this many bytes or greater, it will be uploaded via a multipart request. Default is 20MB. Minimum is 5MB. Maximum is 5GB.
  • multipartUploadSize - when uploading via multipart, this is the part size. The minimum size is 5MB. The maximum size is 5GB. Default is 15MB. Note that S3 has a maximum of 10000 parts for a multipart upload, so if this value is too small, it will be ignored in favor of the minimum necessary value required to upload the file.

s3.getPublicUrl(bucket, key, [bucketLocation])

  • bucket S3 bucket
  • key S3 key
  • bucketLocation string, one of these:
    • "" (default) - US Standard
    • "eu-west-1"
    • "us-west-1"
    • "us-west-2"
    • "ap-southeast-1"
    • "ap-southeast-2"
    • "ap-northeast-1"
    • "sa-east-1"

You can find out your bucket location programatically by using this API: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getBucketLocation-property

returns a string which looks like this:

https://s3.amazonaws.com/bucket/key

or maybe this if you are not in US Standard:

https://s3-eu-west-1.amazonaws.com/bucket/key

s3.getPublicUrlHttp(bucket, key)

  • bucket S3 Bucket
  • key S3 Key

Works for any region, and returns a string which looks like this:

http://bucket.s3.amazonaws.com/key

client.uploadFile(params)

See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property

params:

  • s3Params: params to pass to AWS SDK putObject.
  • localFile: path to the file on disk you want to upload to S3.
  • (optional) defaultContentType: Unless you explicitly set the ContentType parameter in s3Params, it will be automatically set for you based on the file extension of localFile. If the extension is unrecognized, defaultContentType will be used instead. Defaults to application/octet-stream.

The difference between using AWS SDK putObject and this one:

  • This works with files, not streams or buffers.
  • If the reported MD5 upon upload completion does not match, it retries.
  • If the file size is large enough, uses multipart upload to upload parts in parallel.
  • Retry based on the client's retry settings.
  • Progress reporting.
  • Sets the ContentType based on file extension if you do not provide it.

Returns an EventEmitter with these properties:

  • progressMd5Amount
  • progressAmount
  • progressTotal

And these events:

  • 'error' (err)
  • 'end' (data) - emitted when the file is uploaded successfully
    • data is the same object that you get from putObject in AWS SDK
  • 'progress' - emitted when progressMd5Amount, progressAmount, and progressTotal properties change. Note that it is possible for progress to go backwards when an upload fails and must be retried.
  • 'fileOpened' (fdSlicer) - emitted when localFile has been opened. The file is opened with the fd-slicer module because we might need to read from multiple locations in the file at the same time. fdSlicer is an object for which you can call createReadStream(options). See the fd-slicer README for more information.
  • 'fileClosed' - emitted when localFile has been closed.

And these methods:

  • abort() - call this to stop the find operation.

client.downloadFile(params)

See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

params:

  • localFile - the destination path on disk to write the s3 object into
  • s3Params: params to pass to AWS SDK getObject.

The difference between using AWS SDK getObject and this one:

  • This works with a destination file, not a stream or a buffer.
  • If the reported MD5 upon download completion does not match, it retries.
  • Retry based on the client's retry settings.
  • Progress reporting.

Returns an EventEmitter with these properties:

  • progressAmount
  • progressTotal

And these events:

  • 'error' (err)
  • 'end' - emitted when the file is downloaded successfully
  • 'progress' - emitted when progressAmount and progressTotal properties change.

client.downloadBuffer(s3Params)

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

  • s3Params: params to pass to AWS SDK getObject.

The difference between using AWS SDK getObject and this one:

  • This works with a buffer only.
  • If the reported MD5 upon download completion does not match, it retries.
  • Retry based on the client's retry settings.
  • Progress reporting.

Returns an EventEmitter with these properties:

  • progressAmount
  • progressTotal

And these events:

  • 'error' (err)
  • 'end' (buffer) - emitted when the file is downloaded successfully. buffer is a Buffer containing the object data.
  • 'progress' - emitted when progressAmount and progressTotal properties change.

client.downloadStream(s3Params)

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

  • s3Params: params to pass to AWS SDK getObject.

The difference between using AWS SDK getObject and this one:

  • This works with a stream only.

If you want retries, progress, or MD5 checking, you must code it yourself.

Returns a ReadableStream with these additional events:

  • 'httpHeaders' (statusCode, headers) - contains the HTTP response headers and status code.

client.listObjects(params)

See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#listObjects-property

params:

  • s3Params - params to pass to AWS SDK listObjects.
  • (optional) recursive - true or false whether or not you want to recurse into directories. Default false.

Note that if you set Delimiter in s3Params then you will get a list of objects and folders in the directory you specify. You probably do not want to set recursive to true at the same time as specifying a Delimiter because this will cause a request per directory. If you want all objects that share a prefix, leave the Delimiter option null or undefined.

Be sure that s3Params.Prefix ends with a trailing slash (/) unless you are requesting the top-level listing, in which case s3Params.Prefix should be empty string.

The difference between using AWS SDK listObjects and this one:

  • Retries based on the client's retry settings.
  • Supports recursive directory listing.
  • Makes multiple requests if the number of objects to list is greater than 1000.

Returns an EventEmitter with these properties:

  • progressAmount
  • objectsFound
  • dirsFound

And these events:

  • 'error' (err)
  • 'end' - emitted when done listing and no more 'data' events will be emitted.
  • 'data' (data) - emitted when a batch of objects are found. This is the same as the data object in AWS SDK.
  • 'progress' - emitted when progressAmount, objectsFound, and dirsFound properties change.

And these methods:

  • abort() - call this to stop the find operation.

client.deleteObjects(s3Params)

See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObjects-property

s3Params are the same.

The difference between using AWS SDK deleteObjects and this one:

  • Retry based on the client's retry settings.
  • Make multiple requests if the number of objects you want to delete is greater than 1000.

Returns an EventEmitter with these properties:

  • progressAmount
  • progressTotal

And these events:

  • 'error' (err)
  • 'end' - emitted when all objects are deleted.
  • 'progress' - emitted when the progressAmount or progressTotal properties change.
  • 'data' (data) - emitted when a request completes. There may be more.

client.uploadDir(params)

Syncs an entire directory to S3.

params:

  • localDir - source path on local file system to sync to S3
  • s3Params
    • Prefix (required)
    • Bucket (required)
  • (optional) deleteRemoved - delete s3 objects with no corresponding local file. default false
  • (optional) getS3Params - function which will be called for every file that needs to be uploaded. You can use this to skip some files. See below.
  • (optional) defaultContentType: Unless you explicitly set the ContentType parameter in s3Params, it will be automatically set for you based on the file extension of localFile. If the extension is unrecognized, defaultContentType will be used instead. Defaults to application/octet-stream.
  • (optional) followSymlinks - Set this to false to ignore symlinks. Defaults to true.
function getS3Params(localFile, stat, callback) {
  // call callback like this:
  var err = new Error(...); // only if there is an error
  var s3Params = { // if there is no error
    ContentType: getMimeType(localFile), // just an example
  };
  // pass `null` for `s3Params` if you want to skip uploading this file.
  callback(err, s3Params);
}

Returns an EventEmitter with these properties:

  • progressAmount
  • progressTotal
  • progressMd5Amount
  • progressMd5Total
  • deleteAmount
  • deleteTotal
  • filesFound
  • objectsFound
  • doneFindingFiles
  • doneFindingObjects
  • doneMd5

And these events:

  • 'error' (err)
  • 'end' - emitted when all files are uploaded
  • 'progress' - emitted when any of the above progress properties change.
  • 'fileUploadStart' (localFilePath, s3Key) - emitted when a file begins uploading.
  • 'fileUploadEnd' (localFilePath, s3Key) - emitted when a file successfully finishes uploading.

uploadDir works like this:

  1. Start listing all S3 objects for the target Prefix. S3 guarantees returned objects to be in sorted order.
  2. Meanwhile, recursively find all files in localDir.
  3. Once all local files are found, we sort them (the same way that S3 sorts).
  4. Next we iterate over the sorted local file list one at a time, computing MD5 sums.
  5. Now S3 object listing and MD5 sum computing are happening in parallel. As each operation progresses we compare both sorted lists side-by-side, iterating over them one at a time, uploading files whose MD5 sums don't match the remote object (or the remote object is missing), and, if deleteRemoved is set, deleting remote objects whose corresponding local files are missing.

client.downloadDir(params)

Syncs an entire directory from S3.

params:

  • localDir - destination directory on local file system to sync to
  • s3Params
    • Prefix (required)
    • Bucket (required)
  • (optional) deleteRemoved - delete local files with no corresponding s3 object. default false
  • (optional) getS3Params - function which will be called for every object that needs to be downloaded. You can use this to skip downloading some objects. See below.
  • (optional) followSymlinks - Set this to false to ignore symlinks. Defaults to true.
function getS3Params(localFile, s3Object, callback) {
  // localFile is the destination path where the object will be written to
  // s3Object is same as one element in the `Contents` array from here:
  // http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#listObjects-property

  // call callback like this:
  var err = new Error(...); // only if there is an error
  var s3Params = { // if there is no error
    VersionId: "abcd", // just an example
  };
  // pass `null` for `s3Params` if you want to skip downloading this object.
  callback(err, s3Params);
}

Returns an EventEmitter with these properties:

  • progressAmount
  • progressTotal
  • progressMd5Amount
  • progressMd5Total
  • deleteAmount
  • deleteTotal
  • filesFound
  • objectsFound
  • doneFindingFiles
  • doneFindingObjects
  • doneMd5

And these events:

  • 'error' (err)
  • 'end' - emitted when all files are downloaded
  • 'progress' - emitted when any of the progress properties above change
  • 'fileDownloadStart' (localFilePath, s3Key) - emitted when a file begins downloading.
  • 'fileDownloadEnd' (localFilePath, s3Key) - emitted when a file successfully finishes downloading.

downloadDir works like this:

  1. Start listing all S3 objects for the target Prefix. S3 guarantees returned objects to be in sorted order.
  2. Meanwhile, recursively find all files in localDir.
  3. Once all local files are found, we sort them (the same way that S3 sorts).
  4. Next we iterate over the sorted local file list one at a time, computing MD5 sums.
  5. Now S3 object listing and MD5 sum computing are happening in parallel. As each operation progresses we compare both sorted lists side-by-side, iterating over them one at a time, downloading objects whose MD5 sums don't match the local file (or the local file is missing), and, if deleteRemoved is set, deleting local files whose corresponding objects are missing.

client.deleteDir(s3Params)

Deletes an entire directory on S3.

s3Params:

  • Bucket
  • Prefix
  • (optional) MFA

Returns an EventEmitter with these properties:

  • progressAmount
  • progressTotal

And these events:

  • 'error' (err)
  • 'end' - emitted when all objects are deleted.
  • 'progress' - emitted when the progressAmount or progressTotal properties change.

deleteDir works like this:

  1. Start listing all objects in a bucket recursively. S3 returns 1000 objects per response.
  2. For each response that comes back with a list of objects in the bucket, immediately send a delete request for all of them.

client.copyObject(s3Params)

See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#copyObject-property

s3Params are the same. Don't forget that CopySource must contain the source bucket name as well as the source key name.

The difference between using AWS SDK copyObject and this one:

  • Retry based on the client's retry settings.

Returns an EventEmitter with these events:

  • 'error' (err)
  • 'end' (data)

client.moveObject(s3Params)

See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#copyObject-property

s3Params are the same. Don't forget that CopySource must contain the source bucket name as well as the source key name.

Under the hood, this uses copyObject and then deleteObjects only if the copy succeeded.

Returns an EventEmitter with these events:

  • 'error' (err)
  • 'copySuccess' (data)
  • 'end' (data)

Testing

S3_KEY=<valid_s3_key> S3_SECRET=<valid_s3_secret> S3_BUCKET=<valid_s3_bucket> npm test

Tests upload and download large amounts of data to and from S3. The test timeout is set to 40 seconds because Internet connectivity waries wildly.

changelog

4.4.0

  • Export aws-sdk dependency
  • Update dependencies
  • Ability to handle symlinks in uploadDir and downloadDir
  • Expose S3 constants
  • Add downloadStream API

4.3.1

  • Update dependencies

4.3.0

  • fix open file descriptor leak. Thanks Ross Wilson
  • add downloadBuffer API
  • uploadDir: add 'fileUploadStart', 'fileUploadEnd' events
  • downloadDir: add 'fileDownloadStart', 'fileDownloadEnd' events
  • update aws-sdk to 2.0.19

4.2.0

  • use new AWS SDK API to avoid PassThrough stream workaround
  • update aws-sdk to 2.0.17

4.1.1

  • uploadFile and uploadDir now have optional argument defaultContentType.
  • Fixes default Content-Type able to be mutated by third party modules changing the global mime.default_type variable.

4.1.0

  • Content-Type header is now automatically filled out if you do not explicitly provide it or set it to null.

4.0.0

  • support for multipart uploading and downloading. This raises the maximum supported file size to the S3 maximum of 5 TB. It also allows this module to be used to download files which were uploaded via multipart.
  • uploadFile no longer emits 'stream' (possibly multiple times). Instead, it emits 'fileOpened' exactly once, and the parameter can be used to create read streams.
  • uploadFile uses fstat instead of stat. Fixes a possible file system race condition.
  • uploadfile no longer accepts the localFileStat parameter.
  • default maxAsyncS3 increased from 14 to 20
  • added multipartUploadThreshold, multipartUploadSize

3.1.3

  • uploadDir and downloadDir: fix incorrectly deleting files
  • update aws-sdk to 2.0.8

3.1.2

  • add license
  • update aws-sdk to 2.0.6. Fixes SSL download reliability.

3.1.1

  • uploadDir handles source directory not existing error correctly

3.1.0

  • uploadFile computes MD5 and sends bytes at the same time
  • getPublicUrl handles us-east-1 bucket location correctly

3.0.2

  • fix upload path on Windows

3.0.1

  • Default maxAsyncS3 setting change from 30 to 14.
  • Add Expect: 100-continue header to downloads.

3.0.0

  • uploadDir and downloadDir completely rewritten with more efficient algorithm, which is explained in the documentation.
  • Default maxAsyncS3 setting changed from Infinity to 30.
  • No longer recommend adding graceful-fs to your app.
  • No longer recommend increasing ulimit for number of open files.
  • Add followSymlinks option to uploadDir and downloadDir
  • uploadDir and downloadDir support these additional progress properties:
    • filesFound
    • objectsFound
    • deleteAmount
    • deleteTotal
    • doneFindingFiles
    • doneFindingObjects
    • progressMd5Amount
    • progressMd5Total
    • doneMd5

2.0.0

  • getPublicUrl API changed to support bucket regions. Use getPublicUrlHttp if you want an insecure URL.

1.3.0

  • downloadFile respects maxAsyncS3
  • Add copyObject API
  • AWS JS SDK updated to 2.0.0-rc.18
  • errors with retryable set to false are not retried
  • Add moveObject API
  • uploadFile emits a stream event.

1.2.1

  • fix listObjects for greater than 1000 objects
  • downloadDir supports getS3Params parameter
  • uploadDir and downloadDir expose objectsFound progress

1.2.0

  • uploadDir accepts getS3Params function parameter

1.1.1

  • fix handling of directory seperator in Windows
  • allow uploadDir and downloadDir with empty Prefix

1.1.0

  • Add an API function to get the HTTP url to an S3 resource

1.0.0

  • complete module rewrite
  • depend on official AWS SDK instead of knox
  • support uploadDir, downloadDir, listObjects, deleteObject, and deleteDir

0.3.1

  • fix resp.req.url sometimes not defined causing crash
  • fix emitting end event before write completely finished