ImageLensRenderer.vue 2.7 KB

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