Downloader.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <!--
  2. Wrapper to allow an UI element to trigger a file download
  3. The only required property is the File entity to download. It has to be in READY state.
  4. Trigger the download by calling `scope.download` on the event you like.
  5. If you want to display a loading animation while the download request is submitted, you can achieve this with `scope.downloading`
  6. Usage (default button) :
  7. <UiDownloader :file="file"></UiDownloader>
  8. Usage (custom button) :
  9. <UiDownloader :file="file" v-slot="scope">
  10. <v-btn color="primary" :loading="scope.downloading" @click="scope.download">
  11. {{ $t('download') }}
  12. </v-btn>
  13. </UiDownloader>
  14. -->
  15. <template>
  16. <!-- <div @download="download(file)">-->
  17. <div>
  18. <slot :download="download" :downloading="downloading">
  19. <v-btn :loading="downloading" :disabled="downloading" @click="download">
  20. {{ $t('download') }}
  21. </v-btn>
  22. </slot>
  23. </div>
  24. </template>
  25. <script lang="ts">
  26. import {defineComponent, ref, Ref, useContext} from "@nuxtjs/composition-api";
  27. import {QUERY_TYPE} from "~/types/enums";
  28. import {DataProviderArgs} from "~/types/interfaces";
  29. import {File} from "~/models/Core/File";
  30. import {Bool} from "@vuex-orm/core";
  31. export default defineComponent({
  32. props: {
  33. file: {
  34. type: File,
  35. required: true
  36. },
  37. target: {
  38. type: String,
  39. required: false,
  40. default: '_blank'
  41. }
  42. },
  43. setup (props) {
  44. const { $dataProvider } = useContext()
  45. let { file, target } = props
  46. let downloading: Ref<Boolean> = ref(false)
  47. const download = async () => {
  48. if (!file) {
  49. console.error("File is not defined yet, impossible to download")
  50. return
  51. }
  52. if (file.status === 'PENDING') {
  53. console.error("File is not ready yet, impossible to download")
  54. return
  55. }
  56. if (file.status === 'ERROR') {
  57. console.error("An error occurred wilie generating the file, impossible to download")
  58. return
  59. }
  60. if (file.status !== 'READY') {
  61. console.error("File status is not correctly defined")
  62. return
  63. }
  64. if (downloading.value) {
  65. console.error("A download request is already being processed")
  66. return
  67. }
  68. downloading.value = true
  69. const response = await $dataProvider.invoke(
  70. {
  71. type: QUERY_TYPE.FILE,
  72. fileArgs: { fileId: file.id }
  73. } as DataProviderArgs
  74. )
  75. downloading.value = false
  76. const blob = new Blob([response.data], { type: response.data.type })
  77. const url = window.URL.createObjectURL(blob)
  78. const link = document.createElement('a')
  79. link.href = url
  80. link.download = file.name ?? 'document'
  81. link.target = target
  82. link.click()
  83. link.remove()
  84. window.URL.revokeObjectURL(url)
  85. }
  86. return {
  87. download: () => download(),
  88. downloading
  89. }
  90. }
  91. })
  92. </script>