ImageLensRenderer.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <template>
  2. <div>
  3. <div
  4. class="
  5. bg-primary
  6. border-b border-dividerLight
  7. flex flex-1
  8. top-lowerSecondaryStickyFold
  9. pl-4
  10. z-10
  11. sticky
  12. items-center
  13. justify-between
  14. "
  15. >
  16. <label class="font-semibold text-secondaryLight">
  17. {{ $t("response.body") }}
  18. </label>
  19. <div class="flex">
  20. <ButtonSecondary
  21. v-if="response.body"
  22. ref="downloadResponse"
  23. v-tippy="{ theme: 'tooltip' }"
  24. :title="$t('action.download_file')"
  25. :svg="downloadIcon"
  26. @click.native="downloadResponse"
  27. />
  28. </div>
  29. </div>
  30. <div class="flex relative">
  31. <img
  32. class="border-b border-dividerLight flex max-w-full flex-1"
  33. :src="imageSource"
  34. />
  35. </div>
  36. </div>
  37. </template>
  38. <script>
  39. import { defineComponent } from "@nuxtjs/composition-api"
  40. export default defineComponent({
  41. props: {
  42. response: { type: Object, default: () => {} },
  43. },
  44. data() {
  45. return {
  46. imageSource: "",
  47. downloadIcon: "download",
  48. }
  49. },
  50. computed: {
  51. responseType() {
  52. return (
  53. this.response.headers.find(
  54. (h) => h.key.toLowerCase() === "content-type"
  55. ).value || ""
  56. )
  57. .split(";")[0]
  58. .toLowerCase()
  59. },
  60. },
  61. watch: {
  62. response: {
  63. immediate: true,
  64. handler() {
  65. this.imageSource = ""
  66. const buf = this.response.body
  67. const bytes = new Uint8Array(buf)
  68. const blob = new Blob([bytes.buffer])
  69. const reader = new FileReader()
  70. reader.onload = ({ target }) => {
  71. this.imageSource = target.result
  72. }
  73. reader.readAsDataURL(blob)
  74. },
  75. },
  76. },
  77. mounted() {
  78. this.imageSource = ""
  79. const buf = this.response.body
  80. const bytes = new Uint8Array(buf)
  81. const blob = new Blob([bytes.buffer])
  82. const reader = new FileReader()
  83. reader.onload = ({ target }) => {
  84. this.imageSource = target.result
  85. }
  86. reader.readAsDataURL(blob)
  87. },
  88. methods: {
  89. downloadResponse() {
  90. const dataToWrite = this.response.body
  91. const file = new Blob([dataToWrite], { type: this.responseType })
  92. const a = document.createElement("a")
  93. const url = URL.createObjectURL(file)
  94. a.href = url
  95. // TODO get uri from meta
  96. a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
  97. document.body.appendChild(a)
  98. a.click()
  99. this.downloadIcon = "check"
  100. this.$toast.success(this.$t("state.download_started"), {
  101. icon: "downloading",
  102. })
  103. setTimeout(() => {
  104. document.body.removeChild(a)
  105. URL.revokeObjectURL(url)
  106. this.downloadIcon = "download"
  107. }, 1000)
  108. },
  109. },
  110. })
  111. </script>