Unique object names for S3

When creating buckets or objects in S3, I wanted an easy way to create a unique name for each object.

The names to be as short and human readable as possible. (Guids have their place, but I don’t want to look at them).

The Aws Rules for Bucket Naming lists the following guidelines.

  • Bucket names must be at least 3 and no more than 63 characters long.
  • Bucket names must be a series of one or more labels. Adjacent labels are separated by a single period (.). Bucket names can contain lowercase letters, numbers, and hyphens. Each label must start and end with a lowercase letter or a number.
  • Bucket names must not be formatted as an IP address (e.g., 192.168.5.4).
  • When using virtual hosted–style buckets with SSL, the SSL wildcard certificate only matches buckets that do not contain periods. To work around this, use HTTP or write your own certificate verification logic. We recommend that you do not use periods (".") in bucket name

NPM shortid

In the past, I had settled on using the NPM package shortid, but it did not seem to be returning the first character randomly. Based on my recent listen to the Pluralsight course File Storage Using AWS S3 and Glacier: Developer Deep Dive, I want my names to be random, so Amazon can better spread the load out on the hardware.

Custom Id Generation

The bulk of this code comes directly from Tom Spencer’s post – Short ID Generation in JavaScript. His use case was a little different, but you should read it for a more generic approach. I wanted something that took the date into consideration, so I hacked his approach.

Finally, some code

Here is my s3helper.js module

"use strict";

module.exports = (function() {
  const moment = require("moment");

  // Just to ensure we don't start a name with a number, we
  // use alpha only for the prefix.
  const LIST_ALPHA = "abdegjkmnpqrvwxyz";
  const LIST_ALL = "23456789" + LIST_ALPHA;

  const ALL_LENGTH = LIST_ALL.length;
  const BUCKET_ID_LENGTH = 8;
  const OBJECT_ID_LENGTH = 3;

  var getPrefix = function() {
    var retVal = LIST_ALPHA.charAt(
      Math.floor(Math.random() * LIST_ALPHA.length)
    );
    return retVal;
  };

  function getbucketName() {
    var retVal = getPrefix();
    for (var iLoop = 0; iLoop < BUCKET_ID_LENGTH; iLoop++) {
      retVal += LIST_ALL.charAt(Math.floor(Math.random() * ALL_LENGTH));
    }
    return retVal;
  }

  function getobjectName() {
    var retVal = getPrefix();
    for (var iLoop = 0; iLoop < OBJECT_ID_LENGTH; iLoop++) {
      retVal += LIST_ALL.charAt(Math.floor(Math.random() * ALL_LENGTH));
    }

    retVal += "-" + moment().diff("2014-08-26T08:01", "seconds");
    return retVal;
  }

  return {
    bucketName: getbucketName,
    objectName: getobjectName
  };
})();

Using the code is pretty easy.

console.log("s3", s3Helper.bucketName(), s3Helper.objectName());

Which gives me this output in the console.

Print Friendly