본문 바로가기
프로그래밍/nodejs

[220331] multer) 비동기적으로 이미지 1개 업로드하기

by 한코코 2022. 3. 31.

[ 원리 이해하기 ]

중요한건 왜 저렇게 주소를 사용하는지 알아야한다!!!

대충 주소를 때려박다보면 뭐라도 나오겠지-하지말고!!!

 

 

 

 

파일을 올리는 html input 코드

submit을 누르면 form에 적힌 백엔드 서버 4001로 post 요청을 보낸다.

<div id="uploadOne" style="margin-bottom: 150px">
  <h2>파일 한개 업로드</h2>
  <form
    action="http://localhost:4001/file/uploadOne"
    method="post" enctype="multipart/form-data"
  >
    <input type="file" id="fileOne" name="fileOne" />
    <input type="submit" value="파일업로드" />
  </form>
</div>

 

 

 

 

요청을 하기 전에 거치는 미들웨어 multer

미들웨어를 거치면서 어디에 어떻게 저장할지 같은 옵션들이 결정된다.

 

//미들웨어 multer 설정, 객체로 변환해준다
const upload = multer({
  // 저장할 공간을 지정해줌
  storage: multer.diskStorage({
    // 인자 3가지 : 요청, 저장할 파일명, 콜백함수
    destination: (req, file, done) => {
      // 에러에 대한 처리, 저장할 디렉토리 지정
      done(null, "public/img");
    },
    
    filename: (req, file, done) => {
      //파일명을 그냥 적용하면 무조건 그 파일명으로 저장됨
      //= 덮어쓰기 저장될 위험성이 있음. 그래서 새로운 파일을 지정해준다.
      //file.originalname : 상대방이 정해준 파일명
      //그 파일명에서 확장자를 뽑아오는 extname
      const ext = path.extname(file.originalname);
      
      //전체 경로에서 파일만 꺼내오는데, (ext)확장자를 제거함.
      //고유명값을 주기위해 날짜를 더해줌
      //마지막으로 확장자를 더해줌(ext)
      const filename =
        path.basename(file.originalname, ext) + "_" + Date.now() + ext;
        
      //그래서.. 이 길고긴 여정을 거쳐서 만들어진 filename을 저장할것
      //인자 3가지 : 요청, 실제로 사용할 파일, 콜백함수
      done(null, filename);
    },
  }),
  //파일의 용량을 정해주는 limits
  limits: { fileSize: 5 * 1024 * 1024 }, //5MB
});

//업로드 기능을 사용할 곳에만 미들웨어 적용 upload.single()
//upload.single(' 이 안에 있는 이름부터는 파일내용이니까 아직 읽지마 ')
router.post("/uploadOne", upload.single("fileOne"), fileController.uploadOne);

 

 

 

 

 

요청을 받아서 파일을 저장해주고 응답 요청을 보내는 코드

응답요청에서 filename만 분리해내고,

저장한 위치 URL 뒤에 filename을 붙여서 URL을 완성한다.

파일을 저장한 화면을 재렌더링하기 위해서 응답으로 redirect를 보낸다.

 

exports.uploadOne = (req, res) => {
  const { filename } = req.file;
  const filePath = `http://localhost:4001/img/${filename}`;
  res.redirect("http://localhost:3001/file/upload");
};

 

 

 

 

 

리스트를 만들기 위해 post 요청을 보내는 코드

리스트를 만들기 위해서는 백엔드에 있는 파일에 접근해야한다.

upload화면을 그릴때부터 리스트를 만들기위해 post 요청을 보낸댜.

 

exports.upload = async (req, res) => {
  const url = "http://localhost:4001/file/readList";
  const response = await axios.post(url);
  const result = response.data;
  res.render("file.html", { result });
};

 

 

 

 

 

이미지 리스트를 담아서 응답하는 코드

파일처리를 하기위해서 fs 라이브러리 안에 있는 readdir 속성을 불러온다.

readdir는 파일을 저장한 public/img 디렉토리에 저장해서 그 안에 있는 파일명들을 배열로 읽어온다.

exports.readList = async (req, res) => {
  const readBoard = [];
  try {
    fs.readdir("./public/img", (err, data) => {
      data.forEach((v) => readBoard.push(`http://localhost:4001/img/${v}`));
      res.json(readBoard);
    });
  } catch (err) {
    console.log(err);
  }
};

 

 

 

 

 

응답받은 정보를 화면을 그릴때 넘기는 코드

백에서 받아온 파일명 배열을 file.html을 그릴때 사용하도록 { result }로 같이 넘겨준다.

exports.upload = async (req, res) => {
  const url = "http://localhost:4001/file/readList";
  const response = await axios.post(url);
  const result = response.data;
  res.render("file.html", { result });
};

 

 

 

 

 

응답받은 정보로 화면을 그리는 html 코드

nunjucks로 배열 속 정보를 하나씩 나눠서 엘레멘트를 생성하는 코드.

result로 받은 정보를 for 반복문으로 나눠서 img src 안에 코드를 넣어줘서 이미지를 가져온다.

<ul style="display:flex">
  {% for item in result %}
    <li style="margin-right:10px">
      <div>
        <button>x</button>
        <img src={{item}} width="100px" height="100px"></img>
      </div>
    </li>
  {% endfor %}
</ul>

댓글