![見出し画像](https://assets.st-note.com/production/uploads/images/132774634/rectangle_large_type_2_5e0a77b2dff11b379f8ee18f781f663e.jpeg?width=1200)
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レコード読み込んで、各レコードの添付ファイル保存を実行した](https://assets.st-note.com/img/1709456384160-lSgP6g8ATu.png?width=1200)
ローカルのtempディレクトリに、取得したファイルが保存できました。
![tempディレクトリ配下に、2つのファイルが保存された](https://assets.st-note.com/img/1709453784625-WNjuToqvVL.png)
コレジャナイ…
ファイルが保存できたので、中身を確認しました。テキストファイルのmanifest.jsonを開いてみると、json形式ではありませんでした。
![保存したmanifest.jsonの内容は、html形式だった](https://assets.st-note.com/img/1709453987122-9fgfOo47I6.png?width=1200)
エラーページのようなので、ブラウザで表示してみました。
![This link is not valid と書かれた404 not foundエラーページ](https://assets.st-note.com/img/1709454086958-ROlPEr7uUH.png?width=1200)
これ以上のエラー情報が無いので、これはもう少し調べたいところです。クロスドメイン制約かも?と思いましたが、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でステータスも異なる](https://assets.st-note.com/img/1709470666196-jZLtW4dbIr.png?width=1200)
「kintone REST APIで400/520エラーが出た時に確認すべき3つのこと!」を見ると、fileKeyが異なる場合などに520が発生するようです。しかし、fileKeyはダウンロード用のものを指定しているので、合っています。日本語ファイル名がいけないのか、pdfファイルの取得方法に問題があるのか、manifest.jsonの方は404なので、そもそもURLが正しくないと言われています。ますますわからなくなってしまいました。自力で解決するのは限界じゃないかと思うので、明日相談してみます(しょんぼり)
今週も解決できなかった
今週も結局解決できていないままですが、時間切れです。これとは別に、社内用の開発環境でGitHub Actionsで実行してみたいと思い、そちらも準備をしています。いずれにしても原因を特定しないと、やりたいことができない=幸せになれないので、幸せを掴むためにも解決したいです。続きは、また次の週末の予定です。
この記事が気に入ったらサポートをしてみませんか?