LoginSignup
1
1

More than 1 year has passed since last update.

[axios] ファイルダウンロードができない or 空ファイルになってしまう現象の解消

Last updated at Posted at 2021-08-27

フロント側はReact、サーバーサイドはRailsでファイルダウンロードが
うまくいかないケースがあり、それを解消した記事内容になります。

症状としては、axiosのissueにあったこのケースに当たります。
Github | axios/axios | Empty response when responseType is blob or arraybuffer.

サーバーサイドとフロント部分の結合部分なので、
原因の特的ができていなくて引っかかってる人が多そうですね。

私のケースの場合は、railsでheadの記述が不要だったのですが、
それだけじゃよくわからないと思います。
実装をみながら解消方法をみていきましょう。

フロント側の記述

フロント側は以下のようなコードにしています。

$ yarn add file-saver
import  { saveAs } from 'file-saver';
~~

export const fileDownload = () {
  axios
    .get(url, {
      ~~,
      responseType: 'blob',
    })
    .then((response) => {
      const blob = new Blob([response.data], {
        type: response.data.type,
      });
      saveAs(blob, downoloadFileName);
  });
}

(ちなみにaタグにdownload属性をつけるやり方もあります。)

これでフロント側はOKです。
ただ、空ファイルをダウンロードしてしまう場合があります。
const blobの上でブレイクポイントで止めて見ると、以下のような感じです。

スクリーンショット 2021-08-27 11.29.05.png

Blobのサイズが0になっていたり、画像やpdfをダウンロードしようとしているのですが、typeがtext/xmlになっています。

こんなときはサーバーサイド側に問題があります。

サーバーサイド側の記述

私の触ったコードのケースではrailsでsend_data()を使ってfileの実体を送っていました。
記述は以下のような感じにもともとなっていました。

def download
  upload_file = UploadFile.find(file_params)
  file = upload_file.file.blob.download  # モデルでhas_one_attached :fileを記述

  if send_data(file, disposition: 'attachment',
    filename: upload_file.file.blob.filename.to_s,
    ~~
    ~~
    head :no_content  # これがあるとうまくいかない。
  else
    ~~
  end
end

send_data()の引数自体は問題ないのですが、このコードはうまくいきませんでした。
head :no_contentが不要でした。
head :no_contentを削除すると、フロント側のレスポンスが以下のように変わります。

スクリーンショット 2021-08-27 11.22.31.png

Blobのsizeやtypeにちゃんと値が入ります。
ダウンロードした画像も表示できました。

スクリーンショット 2021-08-27 0.54.19.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1