import type { CompressedImage, ImageFormat, UploadImageRequest, UploadImageResponse } from "~/types/image"; import { API_URLS } from "@/utils/api"; export class ImageUploadService { static async getUploadCredentials( _fileExtension: ImageFormat ): Promise { const request: UploadImageRequest = { file_extension: _fileExtension, expires_in: 3600, content_length_range: { min_bytes: 1024, max_bytes: 10485760 } }; const response = await fetch(API_URLS.getUploadUrl, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ data: request }) }); if (!response.ok) { throw new Error( `Failed to get upload credentials: ${response.status} ${response.statusText}` ); } return await response.json(); } static async compressImage( file: File, maxWidth = 1024, quality = 0.8 ): Promise { return new Promise((resolve) => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d")!; const img = new Image(); img.onload = () => { const { width, height } = this.calculateDimensions( img.width, img.height, maxWidth ); canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); canvas.toBlob( (blob) => { const compressedFile = new File([blob!], file.name, { type: "image/jpeg", lastModified: Date.now() }); resolve({ file: compressedFile, preview: canvas.toDataURL("image/jpeg", quality), format: "jpeg" as ImageFormat }); }, "image/jpeg", quality ); }; img.src = URL.createObjectURL(file); }); } static getFileExtension(file: File): ImageFormat { const extension = file.name.split(".").pop()?.toLowerCase(); switch (extension) { case "jpg": case "jpeg": return "jpeg"; case "webp": return "webp"; case "png": return "png"; case "heic": return "heic"; default: return "jpeg"; } } static calculateDimensions( originalWidth: number, originalHeight: number, maxWidth: number ) { if (originalWidth <= maxWidth) { return { width: originalWidth, height: originalHeight }; } const ratio = originalHeight / originalWidth; return { width: maxWidth, height: Math.round(maxWidth * ratio) }; } static async uploadImage( credentials: UploadImageResponse, file: File ): Promise { const formData = new FormData(); Object.entries(credentials.fields).forEach(([key, value]) => { formData.append(key, value); }); formData.append("file", file); const response = await fetch(credentials.url, { method: "POST", body: formData }); if (!response.ok && response.status !== 204) { throw new Error(`خطا در آپلود تصویر`); } return credentials.public_url; } }