LoginSignup
1
1

More than 1 year has passed since last update.

【Node+Vue】ストア+APIを経由してサーバで作ったバイナリファイル受け取りダウンロードさせる

Last updated at Posted at 2020-10-28

リアクティブでSPAでなければ、サーバサイドにPOSTしてファイルをダウンロードさせれば簡単だけど
v-router とか使うと簡単には行かず、困ったのだけれど、
以下の方法で受け渡しできたので備忘録として記載しておく。

【仕様】
・ダウンロードボタンを押すと、サーバ側で作成されたファイルをダウンロードする。

【前提】
・vue から直接サーバ側へはPOSTできない。(ルーターが邪魔する。)
・ストア+API経由でサーバ側とのデータのやり取りはできる。

【サーバ側実装】
今回は、API経由でデータが渡されると、サーバ側でファイルを作成し、base64エンコードした内容を
json形式で { DATA: xxxx } として返すようにした。

【クライアント側実装】
こんな感じ
今回の肝は以下の2箇所。
・base64 をデコードする部分
・blobファイルをダウンロードさせる部分。

methods: {
  /**
   * ダウンロード
   */
  async download() {
    let info = { // api に渡す引数があれば、こんな感じで受け渡す。
      name: "download.csv"
    };
    let data = await this.$store.dispatch("download", { info });

    // base64をデコードする。
    let base64 = data["DATA"];
    let bin = atob(base64.replace(/^.*,/, ''));
    let buffer = new Uint8Array(bin.length);
    for (var i = 0; i < bin.length; i++) {
      buffer[i] = bin.charCodeAt(i);
    }

    // 以下のコードが実行されると、勝手にファイルがダウンロードされる。
    const blob = new Blob([buffer.buffer], { type: 'application/csv'});
    let link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = 'download.csv';
    link.click();
  }
},

download() を呼び出すボタンはこんな感じ。

<v-btn text @click="download" v-bind="attrs" v-on="on">
<v-icon>mdi-download</v-icon>
</v-btn>

直接、サーバサイドにPOSTできれば簡単だったけれど、そうすると他とセオリーが異なってしまう。
ボタンが押されると、すぐ遷移してそちらで処理されるのとは異なり、
ボタンが押されると非同期で axios 通信が行われ、データを受け取った後にダウンロードされることになる。

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