kintoneの添付ファイルをURL指定で表示させる

# はじめに

多くのハッカソンイベントで[kintone](https://kintone.cybozu.co.jp/)がデータベースとして使われます。kintoneには様々なデータを格納することができますが、その中でも画像ファイルなどのバイナリデータを簡単に格納できるのが強みです。

<img width="564" alt="スクリーンショット 2019-10-27 15.15.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/50fd8173-ab5e-5142-8462-7790c20216eb.png">

ところが、この添付ファイルフィールドに格納された画像データを表示させようとすると、途端にハードルが上がります。なぜなら、kintoneでは、添付ファイルを外部から直接表示させる手段はなく、一度ダウンロードさせなくてはならないからです。
[添付ファイルのURLの取得](https://developer.cybozu.io/hc/ja/community/posts/360043151171)

そこで本記事では、添付ファイルをダウンロードせずに、直接URL指定で表示できる方法をご紹介します。
具体的には、AWS LambdaとAPI Gatewayを使います。ですので、これらの知識がある方をターゲットにしています。
そして今回は、Lambdaのコードしかご紹介しませんので、予めご了承ください。

# コードの紹介

では早速、Lambda（Node.js）のコードです。

```javascript
const kintone = require('@kintone/kintone-js-sdk');
const fs = require("fs");

exports.handler = (event, context, callback) => {
    // パラメータを確認
    console.log(`event: ${event}`);
    const recordId = event.id || 1;

    // kintone認証設定（API KEY）　
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken({
        apiToken: process.env.KINTONE_API_TOKEN,
    });

    // コネクション作成
    const kintoneConnection = new kintone.Connection({
        domain: process.env.KINTONE_APP_URI,
        auth: kintoneAuth,
        guestSpaceID: process.env.KINTONE_GUEST_ID, // ゲストスペースID
    });

    // 添付ファイル
    const kintoneFile = new kintone.File({
        connection: kintoneConnection
    });

    // レコード作成
    const kintoneRecord = new kintone.Record({
        connection: kintoneConnection
    });
    
    // アプリID
    const appID = process.env.KINTONE_APP_ID; 

    kintoneRecord.getRecord({
        app: appID,
        id: recordId,
    })
    .then(async resp => {
        const face = resp.record.Face.value[0];  // 'Face'の部分が添付ファイルフィールドのフィールドコードになります
        console.log(`fileKey: ${face.fileKey}`);
        console.log(`contentType: ${face.contentType}`);
        console.log(`size: ${face.name}`);
        console.log(`size: ${face.size}`);
        const fileName = `/tmp/${face.name}`;
        await kintoneFile.download({
            fileKey: face.fileKey,
            outPutFilePath: fileName,
        });
        return fileName;
    })
    .then(fileName => {
        const picture = fs.readFileSync(fileName, "base64");
        callback(null, picture);
    })
    .catch((err) => {
        console.log(err);
        callback(err);
    });
};
```

kintoneのAPI KeyやアプリURL、アプリIDなどはすべて環境変数に設定していますので、Lambdaの実行時にご自分の環境に合わせて設定してください。
また、コードの途中に添付ファイルフィールドのフィールドコードを指定していますので、ここもご自分の環境に合わせて変更してください。
表示させたいレコードIDは、Lambda実行時にidというパラメータで渡すようになっています。やり方は以下の記事などが参考になるはずです。
[LambdaにAPI Gatewayから値を渡す](https://qiita.com/hashimoto048/items/9c8a270c1d86d9f167a0)

# コードのポイント

## kintoneのJavaScript SDKを使う

添付ファイルの扱いは相当面倒なのですが、kintoneのJavaScript SDKを使うと非常に簡単に扱うことができます。
[kintone JS SDKを使って添付ファイル操作](https://developer.cybozu.io/hc/ja/community/posts/360043498952)

ただ、このSDKにも落とし穴があって、Node.jsから利用する場合は、添付ファイルをダウンロードする[パスの指定](https://kintone.github.io/kintone-js-sdk/latest/reference/file/#downloadparams)が必須になります。そう、結局ダウンロードさせないといけないのです。

## Lambdaで/tmpフォルダを使う

今回はAWS Lambdaを使いたいのですが、ご存知の通りLambdaは実行時に環境が調達される仕組みなので永続的にファイルを保存するなどはできません。そこで思いつくのはS3のようなストレージの利用です。
しかし、わざわざ画像を表示するためだけにS3を使うのもどうかと思います（すでにLambdaとAPI Gateway使うやつに言われてなくないですかねｗ）。
で、色々と調べたところ、なんとLambdaからも/tmpフォルダにだけは書き込みができるらしいのです。
[AWS Lambdaでファイル入出力をしてみる](https://qiita.com/yoshidasts/items/ba7ffc5463d7bf603ce9)
今回の使い方では、ファイルは一時的に保存できれば良いので、この方法が良さそうです。

## Base64形式を使う

今回一番ハマったのが、画像データを/tmpフォルダに格納した後に、それを取り出すところでした。
結論から言えば、`fs.readFileSync(fileName, "base64")`で取り出せば大丈夫です。
僕はここをbinaryモードで取り出そうとして丸2日ハマりました。

ということで、この記事だけでは実装するのは難しいかもしれませんが、一番ハマるところだけを紹介したので、後は皆さん頑張ってください。
最後にAPI Gateway経由でブラウザ表示した実行例を載せておきます。

![kintone_attachfile.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/1da2e48a-acf8-7dfd-a508-b2232e47f719.jpeg)