Node.js
axios

[axios] 画像データのレスポンスを取得する際にハマった話

axios を使って画像データ(PNG画像)を取得する REST-API を叩いた際に画像データが期待通りに取得できなくてハマったのでメモを残す。

どういう状況か

前述の通り、axios を使って画像取得の REST-API を実行~画像取得、それにプラスして base64 エンコードした文字列をフロントエンドに送ることが目的。
構成と一連の流れは次のような感じ。

  • 構成

    構成
    フロントエンド ⇔ バックエンドA ⇔ バックエンドB
    
  • 流れ

    1. フロントエンドからバックエンドAに対して画像取得のAPIを実行
    2. バックエンドAは仲介人のような立ち位置で、バックエンドBに対して画像取得のAPIを実行。ここで axios を使う
    3. バックエンドBからバックエンドAに画像が response で返る
    4. バックエンドAは base64 エンコードしてフロントエンドへ返す
    5. フロントエンドは base64 エンコードされて返却された文字列を dataURL で表示する

で、バックエンドBからバックエンドAに返った response にはバイナリデータっぽい文字化けした文字列があって、これを一生懸命 base64 エンコードしていた。

ここで、この 「バイナリデータっぽい文字化けした文字列」が response で返ってきているのがおかしい、と気づけなかったのがハマった原因。

返却される画像データは arraybuffer が正しい

ということで、結論を書くと axios のインスタンスを create する際に設定するパラメータに問題があった。
以下に駄目だったケースと期待通りに動いたケースを示すが、responseType と ContentType に json を指定したのが誤り。画像データを取得する際は、それぞれ arryabuffer と (PNG画像の場合は) image/png を指定する必要があった。

  • 画像取得が正常に行えなかったケース

    設定するパラメータ
    var instance = axios.create({
      'responseType': 'json',
      'headers': {
        'ContentType': 'application/json'
      }
    });
    
  • 画像取得が正常に行えたケース

    設定するパラメータ
    var instance = axios.create({
      'responseType': 'arraybuffer',
      'headers': {
        'ContentType': 'image/png'
      }
    });
    

どうして気づくのが遅れたか

自分自身の知識/経験不足と、しつこいようだが、前掲の「バイナリデータっぽい文字化けした文字列」が返って来ていたのが原因。
「バイナリデータを取得しているんだから、そりゃあ文字化けしてるよね」と思い込んでいた。
なので、base64 エンコードをする際の実装に問題があるとばかり(ここでも)思い込んで、そっちの処理の見直しと試行錯誤ばかりを繰り返していた。

実際は base64 エンコードの処理は問題なくて、画像取得の REST-API を叩く際に axios に設定するパラメータが間違っていた、という話。

おまけ

base64 エンコードの処理はググればいくらでも見つかるけれども、下記のような感じ。

base64エンコードする処理
/**
 * 画像データを base64 エンコード
 *
 * @param {array} imgData
 */
function base64Encode(imgData) {
  // arraybuffer で渡された imgData を base64 エンコードする
  const base64Encoded = imgData.toString('base64');
  return base64Encoded;
}