aタグ押したらBlobデータをダウンロードさせる機能を実装したくてぶち当たった問題とその解決方法について。(Laravel上で使う前提の書き方をしている点に注意)
axiosで行うのは、
- DBにあるPDF情報をまとめているテーブルのレコードIDを指定(送信)
- PDFのBlobとファイル名を取得
の2つ。
最初考えてたもの↓ (これだと目的通り動かない)
DownloadComponent.vue
<template>
<div :id="documentId">
<a @click="download" :href="blob" :download="fileName">
<button type="button" class="btn btn-primary">
ダウンロード
</button>
</a>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: {
documentId: {
type: String,
}
},
data() {
return {
blob: '',
fileName: '',
}
},
methods: {
async download(e) {
const json = await axios.get(
'/pdf/download', {
params: {
id: this.documentId
}
})
const data = json.data
this.fileName = data.name
this.blob = `data:application/pdf;base64,${data.blob}`
}
}
}
</script>
上記の場合、aタグを押すとaxiosの結果よりも先にaタグのブラウザ本来の機能が働いて、空のファイルがダウンロードさせられる。(つまりダウンロードできない)
修正したもの↓
DownloadComponent.vue
<template>
<div :id="documentId">
<button type="button" class="btn btn-primary" @click="download">
ダウンロード
</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: {
documentId: {
type: String,
}
},
methods: {
async download(e) {
const json = await axios.get(
'/pdf/download', {
params: {
id: this.documentId
}
})
const data = json.data
const link = document.createElement('a')
link.href = `data:application/pdf;base64,${data.blob}`
link.download = data.name
link.click()
}
}
}
</script>
改善点
- aタグの要素の状態を生成・実行することで、ブラウザ本来の機能を働かせなくした(DOM操作ではない為)