見出し画像

Fetch API入門(その2)

先週、幸せになりたくてFetch APIを試して、取得したファイルの保存で躓いていました。今週は、「fetch()で取得したファイルを保存できること」を確認します。

幸せになるための準備(続き)

先週は、Fetch APIの使い方を学習するために、kintoneアプリの添付ファイル情報をもとに、添付ファイルをfetch()する手順を試していました。fetch()の実行結果のReadbleStreamからデータを取り出して、ローカルに保存したかったのですが、うまくいきませんでした。

ローカルにファイル保存できた方法

fetch()の実行結果のbodyをPipeTo()で、実行環境の指定ファイルとして定義したWriteStreamに出力できれば良いと考えたのですが、fsのcreateWriteStreamで生成するWriteStreamは、PipeToの変換先のWriteStreamインスタンスとして利用できませんでした。「Node.js Stream を使ってみる」にpipelineを使用する手順が紹介されていたので、pipelineを使うことでローカルのファイルに保存することができました。

const {createWriteStream} = require('fs');
const { pipeline } = require('stream/promises');

// 中略


// ファイルの取得
async function getFile(fileObj){
    try{
        const { fileKey, name, contentType } = fileObj;
        const headers = {
            'X-Requested-With': 'XMLHttpRequest',
            'Host': '<your domain>.cybozu.com:443',
            'X-Cybozu-API-Token': process.env.KINTONE_API_TOKEN
        };
        const resp = await fetch(`https://<your domain>.cybozu.com/k/v1/${name}?fileKey=${fileKey}`, {
            method: 'GET',
            headers,
        })
        .then((resp) => {
            const savePath = `temp/${name}`;
            const distStream = createWriteStream(savePath);
            // レスポンスをファイルに書き出し
            pipeline(resp.body, distStream);
            console.log(`ファイル書き出しOK=>${name}`);
        });
    }
    catch (err) {
        console.error(err);
    }
}
2レコード読み込んで、各レコードの添付ファイル保存を実行した
できたっぽい!

ローカルのtempディレクトリに、取得したファイルが保存できました。

tempディレクトリ配下に、2つのファイルが保存された
lsで確認した結果ファイルがある

コレジャナイ…

ファイルが保存できたので、中身を確認しました。テキストファイルのmanifest.jsonを開いてみると、json形式ではありませんでした。

保存したmanifest.jsonの内容は、html形式だった
これは、エラーページっぽい

エラーページのようなので、ブラウザで表示してみました。

This link is not valid と書かれた404 not foundエラーページ
リクエスト先のURLが正しくないというエラーページ

これ以上のエラー情報が無いので、これはもう少し調べたいところです。クロスドメイン制約かも?と思いましたが、WebページのJavaScript実行ではないので、別の原因のようです。もう一度Fetch APIのドキュメントを読んでみると、fetch()の実行成否は、Response.okがtrueであることを確認しなければならないようです。そこで、fetch()の実行の成否判定を追加して、結果を確認してみることにしました。

fetchに失敗してる!

// ファイルの取得
async function getFile(fileObj){
    try{
        const { fileKey, name, contentType } = fileObj;
        const headers = {
            'X-Requested-With': 'XMLHttpRequest',
            "Content-Type": `${contentType}`,
            'X-Cybozu-API-Token': process.env.KINTONE_API_TOKEN
        };
        const resp = await fetch(`https://1lc011kswasj.cybozu.com/k/v1/${name}?fileKey=${fileKey}`, {
            method: 'GET',
            headers,
        })
        .then((resp) => {
            if(!resp.ok){
                throw new Error(`Network response was not OK [name]${name} [status]${resp.status}`);
            }
            const savePath = `temp/${name}`;
            const distStream = createWriteStream(savePath);
            // レスポンスをファイルに書き出し
            pipeline(resp.body, distStream);
            console.log(`ファイル書き出しOK=>${name}`);
        });
    }
    catch (err) {
        console.error(err);
    }
}

再度実行してみると、fetch()の結果はfalseでした。statusは、PDFファイルの取得は520、jsonファイルの取得は404と、それぞれ異なる結果です。

fetchの結果はどちらもfalseでステータスも異なる
実行結果のコンソール出力

kintone REST APIで400/520エラーが出た時に確認すべき3つのこと!」を見ると、fileKeyが異なる場合などに520が発生するようです。しかし、fileKeyはダウンロード用のものを指定しているので、合っています。日本語ファイル名がいけないのか、pdfファイルの取得方法に問題があるのか、manifest.jsonの方は404なので、そもそもURLが正しくないと言われています。ますますわからなくなってしまいました。自力で解決するのは限界じゃないかと思うので、明日相談してみます(しょんぼり)

今週も解決できなかった

今週も結局解決できていないままですが、時間切れです。これとは別に、社内用の開発環境でGitHub Actionsで実行してみたいと思い、そちらも準備をしています。いずれにしても原因を特定しないと、やりたいことができない=幸せになれないので、幸せを掴むためにも解決したいです。続きは、また次の週末の予定です。

この記事が気に入ったらサポートをしてみませんか?