Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node.js Amazon s3 how to check file exists

I'm trying to figure out how to do the equivalent of fs.exists() on S3.

I succeed in getting the contents of the bucket, but I cannot figure out how to ask S3 if a specific file exists in the bucket (I don't want to download the entire list of files and check client-side, because there are too many files).

For reference: AWS2JS documentation on S3.GET

var s3 = require('aws2js').load('s3', appConfig.awsAccessKeyId, appConfig.awsSecretAccessKey);  
s3.setBucket(appConfig.awsBucketName);

            var folder = encodeURI('reports');
            var url = '?prefix=' + folder;

            s3.get(url,{Contents: null, Key: 'reports/emot_cat_r1180341142.png'},'xml', function (error, data) {
                console.log("Error",error);
                console.log("Data",data);
                true.should.be.true;
                done();
            });

The output

{ Name: 'umusergen', Prefix: 'reports', Marker: {}, MaxKeys: '1000', IsTruncated: 'false', Contents: [ { Key: 'reports/', LastModified: '2013-06-16T17:44:25.000Z', ETag: '"d41d8cd98f00b204e9800998ecf8427e"', Size: '0', Owner: [Object], StorageClass: 'STANDARD' }, { Key: 'reports/emot_cat_r1180341142.png', LastModified: '2013-06-16T23:18:59.000Z', ETag: '"0b04aa9146d36a447019b1aa94be7eb3"', Size: '26374', Owner: [Object], StorageClass: 'STANDARD' }, { Key: 'reports/polarity_r1180341142.png', LastModified: '2013-06-16T23:19:00.000Z', ETag: '"22fd521e0a5e858040082d0d47078532"', Size: '23091', Owner: [Object], StorageClass: 'STANDARD' }, { Key: 'reports/wordcloud_r1180341142.png', LastModified: '2013-06-16T23:19:07.000Z', ETag: '"9f7ee9d2fdce5f460b2c42444edd6efc"', Size: '167164', Owner: [Object], StorageClass: 'STANDARD' } ], '@': { xmlns: { xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/' } } }

The "{Contents: null, Key: '[file path/name]'}" is my attempt to interpret the API instructions referenced above.

As you can see, it just enumerates the contents of the bucket, but I need the API call to check for the existence of a specific file.

Can anyone help? I'm fairly new to all this.

like image 443
metalaureate Avatar asked Jun 16 '13 23:06

metalaureate


People also ask

How do you check if S3 bucket already exists?

To check whether a bucket already exists before attempting to create one with the same name, call the doesBucketExist method. It will return true if the bucket exists, and false otherwise. if (s3. doesBucketExistV2(bucket_name)) { System.

How can I tell if S3 object is file or directory?

With the method "endsWith("/")" you can detect if the S3ObjectSummary is a folder or not. Hope this can helps someone. works like wonders!

How do I view files in S3 bucket?

In AWS Explorer, expand the Amazon S3 node, and double-click a bucket or open the context (right-click) menu for the bucket and choose Browse. In the Browse view of your bucket, choose Upload File or Upload Folder. In the File-Open dialog box, navigate to the files to upload, choose them, and then choose Open.

Where are my files on AWS S3?

You can use the aws s3 ls command to list all the buckets in a region. Objects – An object is a file or folder stored in an S3 bucket. Objects are stored in folders, and folders can contain other folders and files. To get information about an object, you can use the aws s3 ls command.


2 Answers

You have to do it the HTTP way with a HEAD request. A file that does not exist triggers a 404 error. Here's a simple implementation:

var s3 = require('aws2js').load('s3', process.env.AWS_ACCEESS_KEY_ID, process.env.AWS_SECRET_ACCESS_KEY)

s3.setBucket(process.env.AWS2JS_S3_BUCKET)

s3.head(process.argv[2], function (err, res) {
    if (err) {
        console.log(err)
        return
    }
    console.log(res)
})

For testing purposes, invoke it with:

node s3-check.js file/path.foo

Examples:

node s3-check.js foo1.png
{ 'x-amz-id-2': 'BU8rLC35oZdNLh4TkE9Y5+czR5r9hg7kl/EbhkxUF+cA94F41knI2YNs/YG1acQg',
  'x-amz-request-id': '7714B364EC1A27B2',
  date: 'Mon, 17 Jun 2013 06:42:52 GMT',
  'last-modified': 'Tue, 28 May 2013 13:18:12 GMT',
  etag: '"2830931876c37237ae98458a99e86d85"',
  'accept-ranges': 'bytes',
  'content-type': 'image/png',
  'content-length': '1165',
  server: 'AmazonS3' }

node s3-check.js foo0.png
{ [Error: API error with HTTP Code: 404]
  headers:
   { 'x-amz-request-id': '96841B9C0BC5E66D',
     'x-amz-id-2': 'ZMZH9bkrR6nhDkWK1hM+qm0dlzBOYhOZhVyT3nKlMuZgPag//5EhfBuAHZq+9ZRm',
     'content-type': 'application/xml',
     'transfer-encoding': 'chunked',
     date: 'Mon, 17 Jun 2013 06:43:53 GMT',
     server: 'AmazonS3' },
  code: 404 }
like image 146
SaltwaterC Avatar answered Oct 23 '22 01:10

SaltwaterC


The existing answer is a few years old. There's a better way to do this. By using the aws-sdk module, you're provided a nice API through which to do this.

aws-sdk has a function called headObject to look at a file's metadata. Here's example usage

import Promise from 'bluebird'
import AWS from 'aws-sdk'

AWS.config.accessKeyId = Config.Credentials.AWS.accessKeyId
AWS.config.secretAccessKey = Config.Credentials.AWS.secretAccessKey

const s3 = new AWS.S3
Promise.promisifyAll(s3)

const getFileFromS3 = async ({ Bucket, Key })=> {
  try {
    const result = await S3.headObjectAsync({ Bucket, Key })
    console.log(result)
    /* Output:
      { AcceptRanges: 'bytes',
          LastModified: 'Mon, 16 Jan 2017 07:30:19 GMT',
          ContentLength: '6',
          ETag: '"b1946ac92492d2347c6235b4d2611184"',
          ContentType: 'text/plain',
          Metadata: {} }
    */
  } catch (error) {
    if (error.statusCode === 404) console.log('File Not Found')
    console.error('Unexpected Error', error)
  }
}
like image 39
Tim Avatar answered Oct 23 '22 02:10

Tim