Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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

スクリーンショット 2019-10-27 15.15.46.png

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

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

コードの紹介

では早速、Lambda(Node.js)のコードです。

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から値を渡す

コードのポイント

kintoneのJavaScript SDKを使う

添付ファイルの扱いは相当面倒なのですが、kintoneのJavaScript SDKを使うと非常に簡単に扱うことができます。
kintone JS SDKを使って添付ファイル操作

ただ、このSDKにも落とし穴があって、Node.jsから利用する場合は、添付ファイルをダウンロードするパスの指定が必須になります。そう、結局ダウンロードさせないといけないのです。

Lambdaで/tmpフォルダを使う

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

Base64形式を使う

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

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

kintone_attachfile.jpg

mobilebiz
フルスタックエンジニア。趣味は料理。 2014年7月に、留守番電話が文字で届く国内初の留守電サービス「TRANSREC」をリリース。 2015年4月にSmart Communication Award 2015で「自動電話リレーサービス」が最優秀賞を受賞。 2016年2月よりTwilioエヴァンジェリスト。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away