GcsStore examples


This is part of the writeup on Using Google Cloud Storage with Apps Script. By now you should have completed all the steps in Setting up or creating a console projectEnabling APIs and OAuth2 and Using the service account to enable access to cloud storage and now have a project and credentials you can use to create your storage buckets. You can also read more about the background of how all this works at GcsStore overview - Google Cloud Storage and Apps Script

Libraries

You should already have the cGoa library, from when you set up your credentials in  Using the service account to enable access to cloud storage
You'll also need the cGcsStore library on github or at this key.
1w0dgijlIMA_o5p63ajzcaa_LJeUMYnrrSgfOzLKHesKZJqDCzw36qorl

It's not necessary, but I usually also include the cUseful library too, as it has lots of shortcuts and I may use some of them in the examples throughout this post. You'll find that on github or at 
1EbLSESpiGkI3PYmJqWh3-rmLkYKAtCNPi1L2YCtMgo2Ut8xMThfJ41Ex

So my final resource manifest looks like this.

Some examples

These examples are various scenarios of writing and reading different kinds of data, excercising expiry, folderkey, compression and various other capabilities.

Getting started

 Consuming an access token, opening the store, creating a bucket if necessary, setting up lifetime (Im using this one as self cleansing since I want it to go away later) 

  // ive named the goa service account package name and bucket name the same thing
  var bucket = 'xliberation-store';
  var packageName = 'xliberation-store';
  
  // this consumes up the Oauth2 authentication that was set up once off
  var goa = cGoa.make (packageName,PropertiesService.getScriptProperties());
  
  // you can get the project id & accessToken from goa
  var accessToken = goa.getToken();
  var projectId = goa.getPackage().project_id;
  
  // create a new gcs manager
  var gcs = new cGcsStore.GcsStore()
  .setAccessToken (accessToken)
  
  // a bucket can be created like this
  if (!gcs.bucketExists(bucket)) {
    gcs.createBucket (projectId, bucket);
  }

  // open a store with global visibility 
  gcs.setBucket(bucket);
  
  // since im using it as gcs i'll set the lifetime of items in it to 1 day
  gcs.setLifetime (1);

Putting and Getting data

  // do a put & get -- global scope
  gcs.put ("mykey","written to global scope");
  Logger.log(gcs.get ("mykey"));
  
  // an arbitrary scope
  gcs.setFolderKey ('all my friends');
  gcs.put ("mykey","written to " + gcs.getFolderKey() + ' scope');
  Logger.log(gcs.get ("mykey"));
  
  // lets use this function to check that what was got is what was written
  // from now on
  function checkit(key,value,expiry) {
    gcs.put (key,value,expiry);
    var result = gcs.get(key);
    if (result !== value) {
      throw 'expected:' + value + "\ngot:" + result;
    }
  }
  
  // do a put & get -- script scope
  gcs.setFolderKey ('scripts/' + ScriptApp.getScriptId());
  checkit ("mykey","written to " + gcs.getFolderKey() + ' scope');
  
  
  // a document scope
  gcs.setFolderKey ('documents/some document id');
  checkit ("mykey","written to " + gcs.getFolderKey() + ' scope');
  
  
  // users - use whatever syntax you like. I recommend an object name like this
  gcs.setFolderKey ('users/bruce@mcpher.com');
  checkit ("mykey","written to " + gcs.getFolderKey() + ' scope');
  
  // script users
  gcs.setFolderKey ('scripts/' + ScriptApp.getScriptId() + '/users/bruce@mcpher.com');
  checkit("mykey","written to " + gcs.getFolderKey() + ' scope');
  
  // anonymous users can be tracked using the UserProperties service
  var registration = cUseful.UserRegistration.register (PropertiesService.getUserProperties(), 'xliberation_registration_key');
  gcs.setFolderKey ('anonymous/' + registration.id);
  checkit ("mykey","written to " + gcs.getFolderKey() + ' scope - number of visits=' + registration.visits);
  
  
  //objects can be written as well as strings - they are stringified when written and parsed on return 
  //update the registration object
  registration.update();
  gcs.put ("anobject",registration);
  var result = gcs.get ("anobject");
  if (JSON.stringify(result) !== JSON.stringify(registration)) {
    throw 'expected-' + JSON.stringify(registration) + "-got-" + JSON.stringify(result);
  }
  
  
  // since the visibilitykey is arbitrary you can use anything you like
  // so you could create a document/user with
  gcs.setFolderKey ('documents/some document id/anonymous/' + registration.id);
  checkit ("mykey","written to " + gcs.getFolderKey() + ' scope - number of visits=' + registration.visits);
  

Getting the keys in the store

  
  // here's how to get all the unexpired keys for a particular visibility
  Logger.log(gcs.setFolderKey("anonymous").getKeys());
  

Expiration


  // expiration works like this
  // it should find it as it hasnt expired yet
  checkit("expireme","this should be expired in 2 seconds", 2);
  
  // wait 3 seconds, and it should have gone away
  Utilities.sleep (3000);
  if (gcs.get ("expireme")) {
    throw "should have expired";
  }
  else {
    Logger.log('expired ok');
  }

Working with blobs  

GcsStore can write blobs too.
  // writing a blob - lets put them somewhere easy to find
  gcs.setFolderKey("myblobs");
  var blob = UrlFetchApp.fetch(
    'https://lh3.googleusercontent.com/WDw-R5uUz7VnjhPAAyoDYXPWrLKATvUeKeeQk1HA1AFO-tqyVjwmAAKHWDZcJEISO8kRwtV7nQ=s50-h50-e365'
  ).getBlob();
  gcs.put ("ablob",blob);
  var getBlob = gcs.get("ablob");
  if (!blobMatches (blob, getBlob));
  
  // use this to compare blobs
  function blobMatches(a,b) {
    var abytes = a.getBytes();
    var bbytes = b.getBytes();
    if (abytes.length !== bbytes.length) {
      throw 'expected length of ' + abytes.length + ' but got ' + bbytes.length;
    }
    var acontent = a.getContentType();
    var bcontent = b.getContentType();
    
    if (acontent !== bcontent) {
      throw 'expected content of ' + acontent + ' but got ' + bcontent;
    }
    
    if (!abytes.every(function(d,i) { return d === bbytes[i]; })) {
      throw 'bytes are different';
    }
  }
  

Default expiration


By default items don't expire, but you can make them
  // now lets change the default expiry time
  var current = gcs.getDefaultExpiry ();
  gcs.setFolderKey("global")
  .setDefaultExpiry (3);
  
  checkit("expireme1","this should be expired in 3 seconds");
  
  // set it back to whatever it was
  gcs.setDefaultExpiry(current);
  
  Utilities.sleep (3000);
  if (gcs.get ("expireme1")) {
    throw "should have expired";
  }
  else {
    Logger.log('expired ok');
  }

Compressing

GcsStore can compress and uncompress the data on writing/reading if you want it to.
  // we can ask for the data to be compressed for a single call - heres compress with a 10 second expiry
  gcs.put ("compressed" , "this should be compressed", 10 , true);
  Logger.log(gcs.get("compressed"));
  
  // we can also set that as the default
  var current = gcs.getDefaultCompress();
  gcs.setDefaultCompress(true);
  checkit("compress1","this should be compressed by default");
  gcs.setDefaultCompress(current);
  

Predefined ACLS

You can change the predefined ACL of an existing object as in the example below which sets its access to public read.
gcs.patchPredefinedAcl("compress1", "publicRead");

SelfLink

If you want to share an object, you can get its self link like this, which will return a URL to access its metadata directly. If you've set the ACL to publicRead, this would allow you share a file's metadata publicly. To get the link to its content, use getPublicLink
Logger.log(gcs.getSelfLink("compress1"));

PublicLink

If you want to share an object, you can get its self link like this, which will return a URL to access its content directly. If you've set the ACL to publicRead, this would allow you share a file publicly.
Logger.log(gcs.getPublicLink("compress1"));


CORS


GcsStore has methods to enable cors. For more info see Google cloud storage and CORS


More








For more like this, see Google Apps Scripts snippets. Why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available.
Comments