Node.jsからCloud Storageを利用(入門)


サービスアカウントの作成

Google Cloud Platformにアクセスしてサービスアカウントの作成(API)を行います。
ナビゲーションメニュー > APIとサービス > 認証情報 をクリックし画面に移動します。
そしてサービスアカウントを管理をクリックします。

次の画面ではサービスアカウントを作成をクリックします。

サービスアカウントの詳細を各項目入力していきます。

設定項目 設定内容
サービス アカウント名 (任意の名前に設定)
サービスアカウント説明 (各プロジェクトわかりやすいように任意で設定)

入力が終了したら作成をクリックします。

次の項目ではCloud Storageに関するロールを作ります。今回はテストなのでストレージ管理者(フル権限)を選択しました。
使用アプリケーションに応じてロールを変更するようにしましょう。

最後の項目は省略して大丈夫です。
作成したサービスアカウントをクリックし、キーの項目で鍵を追加をクリックし新しい鍵を作成を選択します。

キーのタイプはJSONを選択して「作成」します。ローカルストレージ内にJSONファイルがダウンロードされるので次の項目でそのJSONファイルを使用し、PythonからCloud Storageを操作していきます。

NodeからCloudStorageを操作

Nodeライブラリーのインストール

今回のプロジェクトで必要なライブラリーを順番にインストールしていきます。

npm install @google-cloud/storage

Excelファイルをjavascriptで読み込みこむ為に、npmパッケージのxlsjsをインストールします。

npm i xlsx-populate --save

Cloud Storage上のバケットの準備

GUIからGoogle Cloud Storageにアクセスし、バケットを作成し適当な画像ファイルを準備します。
コンソール画面から ナビゲーションメニュー > Cloud Storage で移動します。
今回はPythonのロゴファイルをダウンロードし、image.pngという名前をつけ保存しました。
Pythonのロゴファイル

Node.jsからCloud Storageに画像ファイルを取得

GCS上のエクセルファイルを取得し、createReadStream()によりBlobデータをメモリー上に読み込みます。その後Node.jsのライブラリsharpによりローカル内にファイルを作成保存する流れになります。

const {Storage} = require('@google-cloud/storage');
const sharp = require('sharp');

const keyFilename = '{キーとなるJSONファイルのパス}';
const bucketName = '{任意の名前で作成したバケット名}';

// バケットの取得
const storage = new Storage({keyFilename: keyFilename});
const bucket = storage.bucket(bucketName);

const file = bucket.file('image.png')
file.download().then(async function(data) {
    const contents = data[0];
    sharp(contents).toFile('output.jpg', (error, info) => {
      if (error) throw error
      console.info(info)
    })

Node.jsからCloud Storageにアクセスしエクセルファイルを取得

GCS上のエクセルファイルを取得し、createReadStream()によりBlobデータをメモリー上に読み込みます。その後XLSX-populate ライブラリによりデータオブジェクトからブックを生成し、エクセルファイルをローカル内に保存します。
サイズの大きいファイルを読み込むとマシーンによってはメモリ不足になります。

const {Storage} = require('@google-cloud/storage');
const XlsxPopulate = require('xlsx-populate');

const keyFilename = '{キーとなるJSONファイルのパス}';
const bucketName = '{任意の名前で作成したバケット名}';

// バケットの取得
const storage = new Storage({keyFilename: keyFilename});
const bucket = storage.bucket(bucketName);

const file = bucket.file('test.xlsx')
file.download().then(async function(data) {
    const contents = data[0];
    XlsxPopulate.fromDataAsync(contents)
    .then(async function (workbook) {
        workbook.toFileAsync("./out.xlsx");
    });
});

ExpressからExcelファイルをダウンロードさせる場合

const XlsxPopulate = require('xlsx-populate');
const {Storage} = require('@google-cloud/storage');

const express = require("express");
const app = express();

const keyFilename = '{キーとなるJSONファイルのパス}';
const bucketName = '{任意の名前で作成したバケット名}';

// バケットの取得
const storage = new Storage({keyFilename: keyFilename});
const bucket = storage.bucket(bucketName);

// -> Express RestAPIs
app.get("/api/download/excel", (req, res, next) => {
    const file = bucket.file('test.xlsx')
    file.download().then(async function(data) {
        const contents = data[0];
        XlsxPopulate.fromDataAsync(contents)
            .then(async (workbook) => {
            return await workbook.outputAsync();
        }).then(data => {
            console.log(data);
            // Set the output file name.
            res.attachment("output.xlsx");
            // Send the workbook.
            res.send(data);
        }).catch(next);
    });
});

// ポート3000でサーバを立てる
const server = app.listen(5000, () => {
    console.log("Node.js is listening to PORT:" + server.address().port);
});

参考にさせていただいた記事

nodeでGCPのCloud Storageの操作 - iMind Developers Blog
node.jsで(はうまくいかなかったのでpythonで)、gcsにあるサイズの大きいjsonlファイルを、mongodbに登録する(メモリふっとばさずに) - Qiita
ExcelをNode.js(javascript)で読み込む方法。xlsxについて解説します。|おちゃカメラ。
【Node】エクセルの中身を読み込む - なんだかGoodVibes
Node.js - Node.jsでbufferに保存されたExcelをコード上で扱いたい|teratail
Node.jsのライブラリsharpでEXIFなどの画像情報を取得してみる | Simple is Beautiful.