LoginSignup
20
20

More than 3 years have passed since last update.

Nuxt.jsでファイルダウンロードしようとしてつまずいた

Last updated at Posted at 2019-05-25

やりたいこと

クライアントからの要求でPDFを作成し、ダウンロードさせる。

完成形はこちら
https://codesandbox.io/s/nuxtdownloadsample-t5itl?fontsize=14

構成

ダウンロードボタンを押すとaxios.getでapiに問い合わせる。
response.dataでpdfを受け取り、aタグのリンククリックを偽装する。

pages/index.vue
  methods: {
    download() {
      axios
        .get("/api/pdf/test", {
          responseType: "blob"
        })
        .then(response => {
          const blob = new Blob([response.data], { type: "application/pdf" });

          const url = (window.URL || window.webkitURL).createObjectURL(blob);
          const a = document.createElement("a");
          a.href = url;
          a.download = "test.pdf";
          // aタグ要素を画面に一時的に追加する
          document.body.appendChild(a);
          a.click();
          // 不要になったら削除.
          document.body.removeChild(a);
        });
    }
  }

api側は、pdfkitでpdfを生成してresに流し込む。

api/pdf.js
router.get("/test", (req, res, next) => {
  res.setHeader("Content-disposition", "attachment; filename=" + "test.pdf");
  res.setHeader("Content-type", "application/pdf");

  let doc = new PDFDocument();
  doc.pipe(res);

  samplePdf(doc);
});

困ったこと

ダウンロードされたpdfの中身が真っ白になった。
具体的には、
* 文字や図形を埋め込んでも表示されない
* 改ページを埋め込むと正しくされている
* 文字にurlリンクを埋め込むと文字は表示されないがリンクの下線は表示され、クリックが動作する

試したこと

  1. api側でファイルを保存してみる
    → 正しくpdfができている

  2. response.dataの中身を見る
    → 「%PDF-1.3」から始まるデータなので正しそう

  3. <a>タグを追加してhrefで呼び出す。
    → うまくいく
    → でも先にファイルを作っておくのは要件に合わないしアクセス制御も面倒...

原因

getのオプションにresponseType="blob"を指定する必要があるらしい。

pages/index.vue
  methods: {
    download() {
      axios
        .get("/api/pdf/test", {
          responseType: "blob"        // ☆これがポイント
        })

axiosのコンフィグを上から見てそれっぽいのを試してたら突然できた。
Qiitaに書こうとしてたら見つけた記事→https://qiita.com/Ryoma0413/items/bc1b75e5e3736ac1fef5

まとめ

公式ドキュメント重要!

20
20
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
20
20