diff --git a/src/Target/components/FavoriteImageInput/index.tsx b/src/Target/components/FavoriteImageInput/index.tsx index 78e8aa30..c8903f6d 100644 --- a/src/Target/components/FavoriteImageInput/index.tsx +++ b/src/Target/components/FavoriteImageInput/index.tsx @@ -1,28 +1,59 @@ -import { useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { IcCamera, ImgBook } from '../../../assets'; +import { getPresignedUrl, uploadFile } from '../../util/api'; import * as S from './FavoriteImageInput.style'; interface FavoriteImageInputProps { imgFile: string; uploadImage: (file: string) => void; + changePresignedFileName: (fileName: string) => void; } -function FavoriteImageInput({ imgFile, uploadImage }: FavoriteImageInputProps) { +function FavoriteImageInput({ + imgFile, + uploadImage, + changePresignedFileName, +}: FavoriteImageInputProps) { const imgRef = useRef(null); + const [presignedData, setPresignedData] = useState({ + url: '', + fileName: '', + }); - const handleImageUpload = () => { + useEffect(() => { + const fetchPresignedData = async () => { + const { url, fileName } = await getPresignedUrl('/api/images/book'); + setPresignedData({ url, fileName }); + changePresignedFileName(fileName); + }; + + fetchPresignedData(); + }, []); + + const handleImageUpload = async (): Promise => { const fileInput = imgRef.current; if (fileInput && fileInput.files && fileInput.files.length > 0) { const file = fileInput.files[0]; - const reader = new FileReader(); - reader.readAsDataURL(file); + const base64Reader = new FileReader(); + base64Reader.readAsDataURL(file); + base64Reader.onloadend = () => { + if (base64Reader.result !== null) { + uploadImage(base64Reader.result as string); + } + }; - reader.onloadend = () => { - if (reader.result !== null) { - uploadImage(reader.result as string); + const binaryReader = new FileReader(); + binaryReader.readAsArrayBuffer(file); + binaryReader.onloadend = async () => { + if (binaryReader.result !== null) { + await uploadFile( + presignedData.url, + binaryReader.result as ArrayBuffer, + file.type, + ); } }; } diff --git a/src/Target/page/TargetPage/index.tsx b/src/Target/page/TargetPage/index.tsx index fb1b272d..7e49baa7 100644 --- a/src/Target/page/TargetPage/index.tsx +++ b/src/Target/page/TargetPage/index.tsx @@ -1,4 +1,5 @@ import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import Header from '../../../components/common/Header'; import CompleteButton from '../../components/CompleteButton'; @@ -8,10 +9,14 @@ import * as S from './TargetPage.style'; function TargetPage() { const [imgFile, setImgFile] = useState(''); + const [presignedFileName, setPresignedFileName] = useState(''); const [name, setName] = useState(''); + const navigate = useNavigate(); const handleClickCompleteButton = () => { - // API 쏘기... + navigate('/select-book', { + state: { presignedFileName: presignedFileName, name: name }, + }); }; return ( @@ -28,6 +33,9 @@ function TargetPage() { setImgFile(file)} + changePresignedFileName={(filename) => + setPresignedFileName(filename) + } /> diff --git a/src/Target/util/api.ts b/src/Target/util/api.ts new file mode 100644 index 00000000..476db6cc --- /dev/null +++ b/src/Target/util/api.ts @@ -0,0 +1,34 @@ +import { AxiosResponse } from 'axios'; + +import { api } from '../../libs/api'; + +interface PresignedUrlResponse { + data: { + url: string; + fileName: string; + }; +} + +const getPresignedUrl = async ( + endpoint: string, +): Promise<{ url: string; fileName: string }> => { + const response: AxiosResponse = await api.get(endpoint); + return { + url: response.data.data.url, + fileName: response.data.data.fileName, + }; +}; + +const uploadFile = async ( + url: string, + data: ArrayBuffer, + contentType: string, +): Promise => { + await api.put(url, data, { + headers: { + 'Content-Type': contentType, + }, + }); +}; + +export { getPresignedUrl, uploadFile };