-
[Toy Project 기록하기 4] 파일 업로드하기 with multerFrontend/Projects 2023. 3. 5. 22:08
프로젝트에서 이미지 파일을 받아 업로드 하는 기능이 필요함에 따라 multer를 도입하게 됐습니다.
multer
파일 업로드 시 사용하는 node.js의 미들웨어이며 오직 multipart/form-data에서만 동작합니다.
multer 설치하기
npm install multer
피드를 업로드하는 화면에서 이미지를 받아 업로드 하는 기능을 추가해보려고 합니다.
/feed로 post 요청 시 이미지를 업로드 할 수 있도록 라우터에 정의합니다. photoUpload 미들웨어를 통과한 뒤 uploadFeed 함수로 넘어갑니다.
// feedRouter.ts import express from 'express'; import { photoUpload } from '../server/middlewares'; const feedRouter = express.Router(); // 한 개의 파일을 업로드 할 수 있습니다. 'photo'는 form을 통해 전송되는 파일 name feedRouter.post('/', photoUpload.single('photo'), uploadFeed); // ...
multer의 diskStorage 엔진은 파일을 디스크에 저장하기 위한 모든 제어기능을 제공하며 destination, filename 옵션이 주어집니다. destination은 업로드 한 파일을 저장할 위치를 결정하고, filename은 폴더 안에 저장되는 파일명을 결정합니다.
// middlewares.ts import multer from 'multer'; const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads/photos/'); }, filename: function (req, file, cb) { cb(null, `${Date.now()}_${file.originalname}`); }, }); export const photoUpload = multer({ storage, // 파일 크기 제한 limits: { fileSize: 3000000, }, });
이미지가 업로드되면 req.file에 나타나게 됩니다.
export const uploadFeed = async (req, res) => { try { const { title, text } = req.body; // req.file은 multer가 파일을 업로드 했을 때만 생성됨. // path는 optional하기 때문에 구조분해할당 불가 const path = req.file?.path; const newFeed = await Feed.create({ title, text, photo: path, }); return res.status(200).send(newFeed); } catch (error) { return res.status(500).send({ message: DEFAULT_ERROR_MESSAGE }); } };
피드를 업로드하는 페이지에서 이미지를 업로드하는 방법에 대해 알아보겠습니다.
먼저 multipart/form-data 타입의 폼을 만들어 준 뒤, handlePhotoFileChange를 통해 이벤트 발생 시 preview에 추가해 이미지를 미리 보게 했고 form이 submit될 때 /feed로 formData를 post 요청을 보냈습니다.
export default function UploadFeed() { const [preview, setPreview] = useState(); onst handlePhotoFileChange = async (event) => { const file = event.target.files[0]; file && setPreview(URL.createObjectURL(file)); }; const onValid = ({ title, text, photoFile, }) => { const formData = new FormData(); formData.append('title', title); formData.append('text', text); photoFile && formData.append('photo', photoFile); return axiosInstance.post(`/feed`, formData); }; return ( <form method="POST" encType="multipart/form-data" onSubmit={handleSubmit(onValid)} > // ... <div> <label htmlFor="photoFile"> 사진 </label> <input id="photoFile" type="file" accept="image/*" {...register('photoFile', { onChange: handlePhotoFileChange, })} /> </div> <div> {preview && ( <img src={preview} alt="preview"></img> )} </div> {isError && isAxiosError(error) && ( <p>{error.response?.data.message}</p> )} <div> <button type="submit" disabled={isLoading} > {isLoading ? '업로드 중' : '올리기'} </button> </div> </form> ); }
🧗♀️ 제가 진행한 프로젝트가 궁금하다면
🔽 프론트엔드는 이곳에서 확인하실 수 있습니다.
https://github.com/Team-Madstone/doljabee-fe
GitHub - Team-Madstone/doljabee-fe: Climbing Community
Climbing Community. Contribute to Team-Madstone/doljabee-fe development by creating an account on GitHub.
github.com
🔽 백엔드는 이곳에서 확인하실 수 있습니다.
https://github.com/Team-Madstone/doljabee-be
GitHub - Team-Madstone/doljabee-be: Climbing Community
Climbing Community. Contribute to Team-Madstone/doljabee-be development by creating an account on GitHub.
github.com
참고 자료
반응형'Frontend > Projects' 카테고리의 다른 글
[Toy Project 기록하기 6] 회원가입 & 이메일 인증하기 (0) 2023.03.16 [Toy Project 기록하기 5] 세션 인증 방식 vs 토큰 인증 방식 (0) 2023.03.09 [Toy Project 기록하기 3] React Hook Form 활용하기 (0) 2023.03.04 [Toy Project 기록하기 2] axios로 HTTP 요청 보내기 (0) 2023.02.19 [Toy Project 기록하기 1] 커뮤니티 사이트 기획하기 (0) 2023.02.05