MERN stack으로 이미지 업로드

채희태·2022년 9월 8일

Drop-zone 사용하기

drop-zone은 이미지파일을 drop하는 zone이다.
파일을 드래그하거나 클릭하여 업로드할 수 있다.

설치는 다음과 같다.
npm i drop-zone

import React from 'react'
import Dropzone from 'react-dropzone'

<Dropzone onDrop={onDrop}>
  {({getRootProps, getInputProps}) => (
    <section>
      <div {...getRootProps()}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
    </section>
  )}
</Dropzone>

onDrop 으로 함수를 정의할 수 있다.
이 함수로 서버에 이미지 파일을 저장할 것이다.
p태그 부분은 드롭되는 존이므로 원하는대로 ui를 생성해주면 된다.


onDrop함수 만들기

const onDrop = (files) => {
  let formData = new FormData();
  formData.append("file", files[0]);
  axios
    .post("http://localhost:7000/api/product/image", formData)
    .then((res) => {
      if (res.data.success) {
        setImage([...image, res.data.fileName]);
      } else {
        alert("이미지 업로드 실패");
      }
    });

setImage로 서버에서 보내주는 이미지파일 정보(파일 이름)를 state에 저장한다.
FormData()로 빈 FormData객체를 생성한다.
그리고 빈 객체에 'file' 키와 files (드롭된 이미지 파일) 밸류를 넣어준다.
그리고 axios로 서버에 post해준다.


server에 이미지 파일 저장하기

client에서 지정해준 경로로 서버에 이미지 파일을 저장한다.
이 때, multer 라이브러리로 이미지 파일을 저장한다.
multer는 diskstorage engine를 사용해 파일을 디스크에 저장할 수 있게 해준다.

설치는 다음과 같다.
npm i multer

이미지 파일을 저장할 폴더를 생성한다.
backend/public

정적파일인 이미지파일을 express가 웹브라우저로 보내줄 수 있게 해준다.
이를 통해 backend/public폴더에 저장된 이미지파일을 웹브라우저에서 불러올 수 있다.

app.use('/', express.static("./public"))

'http://localhost:포트번호/파일명'
으로 불러올 수 있다.
관련 참고

backend/server/routes/product.js

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "public");
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
    cb(null, file.fieldname + "-" + uniqueSuffix);
  },
});
const upload = multer({ storage: storage }).single("file");

destination의 cb에 두번 째 인자로 이미지 파일을 저장할 폴더를 넣는다.
filename의 uniqueSuffix는 이미지 파일의 고유 이름을 생성해준다.
변수 upload로 multer함수를 저장한다. (multer에는 인자로 storage를 넣어줌.)

router.post("/image", (req, res) => {
  //이미지 파일 저장하기
  upload(req, res, (err) => {
    if (err) {
      return res.json({ success: false, err });
    }
    return res.json({
      success: true,
      filePath: res.req.file.path,
      fileName: res.req.file.filename,
    });
  });
});

client에서 보낸 post 메서드에 response를 보낸다.


업로드한 사진 브라우저에서 불러오기

서버에 저장해 놓은 정적파일인 이미지파일을 express가 웹브라우저로 보내줄 수 있게 해준다.
이를 통해 로컬 backend/public폴더에 저장된 이미지파일을 웹브라우저에서 불러올 수 있다.

app.use('/', express.static("./public"))

'http://localhost:포트번호/파일명'
으로 불러올 수 있다.
관련 참고

<div>
  {image.map((img, index) => (
    <img
      key={index}
      src={`http://localhost:7000/${img}`}
      style={{ width: "13rem", height: "13rem" }}
      ))}
</div>
profile
기록, 공부, 활용

0개의 댓글