From b1161c8a3aa6364e18722cbe672b9106a2bbecd6 Mon Sep 17 00:00:00 2001 From: hyohyo12 <129946082+hyohyo12@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:03:37 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=A6=AC?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EC=A7=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20#146?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/image/index.ts | 64 ++++++++++++++++++++++++++++----- frontend/src/constants/api.ts | 2 ++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/frontend/src/api/image/index.ts b/frontend/src/api/image/index.ts index 0ef1e3af..6ba6f4b8 100644 --- a/frontend/src/api/image/index.ts +++ b/frontend/src/api/image/index.ts @@ -1,12 +1,9 @@ import { axiosInstance } from '../axiosInstance'; import { PreSignedURLResponse } from '../../types'; import { END_POINTS, IMAGE_EXTENSIONS } from '@/constants/api'; -import { THREE_MB } from '../../constants/api'; +import { IMAGE_HEIGHT, IMAGE_WIDTH, THREE_MB } from '../../constants/api'; -export const generatePreSignedPost = async ( - dirName: string, - extension: string, -) => { +const generatePreSignedPost = async (dirName: string, extension: string) => { const { data } = await axiosInstance.post( END_POINTS.PRE_SIGNED_POST, { @@ -17,12 +14,12 @@ export const generatePreSignedPost = async ( return data; }; -export const getExtensionByFile = (file: File) => { +const getExtensionByFile = (file: File) => { const extension = file.name.split('.').pop(); return extension ? extension.toLowerCase() : null; }; -export const validateFile = (file: File, extension: string | null) => { +const validateFile = (file: File, extension: string | null) => { return !( !extension || !IMAGE_EXTENSIONS.has(extension) || @@ -30,6 +27,51 @@ export const validateFile = (file: File, extension: string | null) => { ); }; +const resizeImage = async ( + file: File, + width: number, + height: number, +): Promise => { + return new Promise((resolve, reject) => { + const img = new Image(); + const reader = new FileReader(); + + reader.onload = (event) => { + if (event.target?.result) { + img.src = event.target.result as string; + } + }; + img.onload = () => { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + if (!ctx) { + reject(new Error('Canvas Context Get Error')); + return; + } + canvas.width = width; + canvas.height = height; + ctx.drawImage(img, 0, 0, width, height); + canvas.toBlob( + (blob) => { + if (blob) { + const resizedFile = new File([blob], file.name, { + type: file.type, + }); + resolve(resizedFile); + } else { + reject(new Error('Blob Conversion Error')); + } + }, + file.type, + 0.9, + ); + }; + img.onerror = (error) => reject(error); + reader.onerror = (error) => reject(error); + reader.readAsDataURL(file); + }); +}; + export const uploadImage = async (file: File, dirName: string) => { const extension = getExtensionByFile(file); if (!validateFile(file, extension)) { @@ -38,11 +80,17 @@ export const uploadImage = async (file: File, dirName: string) => { ); } const preSignedPost = await generatePreSignedPost(dirName, extension!); + let resizedImage: File; + try { + resizedImage = await resizeImage(file, IMAGE_WIDTH, IMAGE_HEIGHT); + } catch (err) { + throw new Error(`이미지 리사이즈 중 에러가 발생했습니다 : ${err}`); + } const formData = new FormData(); Object.entries(preSignedPost.fields).forEach(([key, value]) => { formData.append(key, value); }); - formData.append('file', file); + formData.append('file', resizedImage); return fetch(preSignedPost.url, { method: 'POST', body: formData, diff --git a/frontend/src/constants/api.ts b/frontend/src/constants/api.ts index 8d5d6d6c..4f9e6186 100644 --- a/frontend/src/constants/api.ts +++ b/frontend/src/constants/api.ts @@ -47,3 +47,5 @@ export const IMAGE_EXTENSIONS = new Set([ ]); export const THREE_MB = 3145728; +export const IMAGE_WIDTH = 1200; +export const IMAGE_HEIGHT = 900;