files.ts 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. import type { FileUploaded } from '@shared/components/Form/fields/FieldFile/types'
  3. import { useApplicationStore } from '@shared/stores/application'
  4. export interface ImageFileData {
  5. name: string
  6. type: string
  7. content: string
  8. }
  9. export const blobToBase64 = async (blob: Blob) =>
  10. new Promise<string>((resolve, reject) => {
  11. const reader = new FileReader()
  12. reader.onload = () => resolve(reader.result as string)
  13. reader.onerror = () => reject(reader.error)
  14. reader.readAsDataURL(blob)
  15. })
  16. export const convertFileList = async (
  17. filesList?: Maybe<FileList>,
  18. ): Promise<ImageFileData[]> => {
  19. const files = Array.from(filesList || [])
  20. const promises = files.map(async (file) => {
  21. return {
  22. name: file.name,
  23. type: file.type,
  24. content: await blobToBase64(file),
  25. }
  26. })
  27. return Promise.all(promises)
  28. }
  29. export const loadImageIntoBase64 = async (
  30. src: string,
  31. alt?: string,
  32. ): Promise<string | null> => {
  33. const img = new Image()
  34. img.crossOrigin = 'anonymous'
  35. const promise = new Promise<string | null>((resolve) => {
  36. img.onload = () => {
  37. const canvas = document.createElement('canvas')
  38. canvas.width = img.width
  39. canvas.height = img.height
  40. const ctx = canvas.getContext('2d')
  41. ctx?.drawImage(img, 0, 0, img.width, img.height)
  42. const mime = img.alt?.match(/\.(jpe?g)$/i) ? 'image/jpeg' : 'image/png'
  43. try {
  44. const base64 = canvas.toDataURL(mime)
  45. resolve(base64)
  46. } catch {
  47. resolve(null)
  48. }
  49. }
  50. img.onerror = () => {
  51. resolve(null)
  52. }
  53. })
  54. img.alt = alt || ''
  55. img.src = src
  56. return promise
  57. }
  58. export const canDownloadFile = (type?: Maybe<string>) => {
  59. return Boolean(type && type !== 'application/pdf' && type !== 'text/html')
  60. }
  61. export const canPreviewFile = (type?: Maybe<string>) => {
  62. if (!type) return false
  63. const { config } = useApplicationStore()
  64. const allowedPreviewContentTypes =
  65. (config['active_storage.web_image_content_types'] as string[]) || []
  66. return allowedPreviewContentTypes.includes(type)
  67. }
  68. export const convertFilesToAttachmentInput = (
  69. formId: string,
  70. attachments?: FileUploaded[],
  71. ) => {
  72. const files = attachments?.map((file) => ({
  73. name: file.name,
  74. type: file.type,
  75. }))
  76. if (!files || !files.length) return null
  77. return {
  78. files,
  79. formId,
  80. }
  81. }