GoogleAppScriptからS3にバイナリデータをPut

前にS3にテキストファイルをアップロードする方法はやったが、ソースコードを見るとバイナリデータには対応していないことがわかった。
Googleで検索しても全然出てこなかったので、今回はS3ライブラリにバイナリデータのアップロードも対応するよう実装した。

なお、getObject等の実装は今時点ではやっていない。追々できたらなあと思う。

事前準備

  • GoogleAppScriptの準備
  • S3ライブラリ(MB4837UymyETXyn8cv3fNXZc9ncYTrHL9)の登録
  • Amazon S3に書き込みできるユーザの作成、アクセストークン・シークレットトークンの発行

バイナリデータからMD5するスクリプトの追加

先日、今回のために実装したGoogleAppScriptでByte[]のMD5計算機能
ソースコードをプロジェクトに追加。

S3ライブラリの修正

S3ライブラリはそのままではバイナリデータのMD5を計算しないのでメソッドを追加/オーバーライトしてやる。

  • 上書)S3.putObject() :Content-TypeをチェックしバイナリデータならBlob.getBytes()する
  • 追加)S3Request.setBinaryContent() :contentの登録時、明示的にバイナリデータとし、型チェックを行わない
  • 上書)S3Request.getContentMd5_() :MD5計算時、contentの型に応じて計算方法をスイッチする

上記修正をコードにするとこちら。

/**
 * My extensions for S3 Library (MB4837UymyETXyn8cv3fNXZc9ncYTrHL9)
 *                              https://github.com/eschultink/S3-for-Google-Apps-Script/
 */



/**
 * S3.S3.prototype.putObject()の上書き
 */
S3.S3.prototype.putObject = function(bucket, objectName, object, options) {
  options = options || {};

  var request = new S3.S3Request(this);
  request.setHttpMethod('PUT');
  request.setBucket(bucket);
  request.setObjectName(objectName);
  
  var failedBlobDuckTest = !(typeof object.copyBlob == 'function' &&
                      typeof object.getDataAsString == 'function' &&
                      typeof object.getContentType == 'function'
                      );
  
  //wrap object in a Blob if it doesn't appear to be one
  if (failedBlobDuckTest) {
    object = Utilities.newBlob(JSON.stringify(object), "application/json");
    object.setName(objectName);
  }
  
  var contentType = object.getContentType();
  
  // Content-Typeに応じてBlobからのデータ取得方法を切り替える
  if(/^text\//.test(contentType)) {
    request.setContent(object.getDataAsString());
  }
  else if(/^application\/(octet-stream|(x-)?gzip)/.test(contentType)) {
    request.setBinaryContent(object.getBytes());
  }
  else {
    request.setContent(object.getDataAsString());
  }
  request.setContentType(contentType);  
  
  request.execute(options);  
};


/**
 * S3Requestにバイナリデータを登録
 */
S3.S3Request.prototype.setBinaryContent = function(content) {
  this.content = content;
  return this;
};


/**
 * S3.S3Request.prototype.getContentMd5_()の上書き
 * バイナリデータに対応
 */
S3.S3Request.prototype.getContentMd5_ = function() {
  if (this.content.length > 0) {
    if(typeof(this.content) === "string") {
      return Utilities.base64Encode(Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, this.content, Utilities.Charset.UTF_8));
    }
    else {
      if(!(this._md5checksum)) {
        this._md5checksum = new Md5CheckSum(this.content);
      }
      return this._md5checksum.getBase64String();
    }
  } else {
    return ""; 
  }
};

このファイルをS3Extension.gsみたいに適当な名前でプロジェクトに追加。

以上で準備は終了。

動作確認

以下のテストコードで動作確認。

// AWS S3 STORE CONFIG
var S3_BUCKET_NAME = "PLACEYOURS3BUCKETNAME";
var S3_FILENAME_PREFIX = "google-app-script-sample";

// AWS IAM USER PERMITTED TO WRITE S3 BUCKET ABOVE
var S3_ACCESS_TOKEN = "PLACEYOURS3ACCESSTKN";
var S3_SECRET_TOKEN = "PLACEYOURS3SECRETTOKENHEREANDTHENITWORKS";


function upload(blob, filename) {
  filename = !(filename) ? blob.getName() : filename;
  
  var s3 = S3.getInstance(S3_ACCESS_TOKEN, S3_SECRET_TOKEN, {logRequests: false, echoRequestToUrl: false});
  s3.putObject(S3_BUCKET_NAME, S3_FILENAME_PREFIX + "/" + filename, blob, {logRequests: false});
}


// 実際のテストコード
function S3Upload_test() {
  var text = "000000000000000000000000001";
  
  // RAW TEXT
  var blobRaw = Utilities.newBlob(text);
  blobRaw.setName("raw-text.txt");
  blobRaw.setContentType("text/plain");
  upload(blobRaw);
  
  // GZIP COMPRESSED
  var blobCompressed = Utilities.gzip(blobRaw);
  blobCompressed.setName(blobRaw.getName() + ".gz");
  blobCompressed.setContentType("application/x-gzip");
  upload(blobCompressed);
}

上記の”S3Upload_test()”を実行すれば、所定の位置にraw-text.txt(平文)およびraw-text.txt.gz(gzip圧縮)がアップロードされる。

S3に保存されたいろいろなデータを手軽に分析するツールは揃って来ているので、お手軽お安く分析したいのであればS3に保存するのが良い、ということはよく言われている。

コンピューティング環境であればAmazon Lambdaもあり、もちろんそれも使えるが
GSuiteに保存されるデータ(例えばGmail添付ファイルだったり、Spreadsheet上のテーブルだったり)を扱いたいのであれば、GoogleAppScriptで実装したほうが(個人的には)早いと思うし
S3に保存したデータはデータ量課金だから非圧縮ファイルを置くのは抵抗あるし
Amazon Athenaはgz形式にも対応しているし、、、、
ということで今回のGoogleAppSciptからバイナリデータをS3にアップロード機能を作った。
今後データの収集に活用していきたい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です