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

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

by 한코코 2022. 3. 31.

파일을 올리는 html input 코드

<form
  action="http://localhost:4001/file/uploadMany"
  method="post"
  enctype="multipart/form-data"
>
  <input type="file" id="fileMany" name="fileMany" multiple/>
  <input type="submit" value="파일업로드" />
</form>

 

 

 

 

요청을 하기 전에 거치는 미들웨어 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("/uploadMany", upload.array("fileMany"), fileController.uploadMany);

 

 

 

 

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

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

exports.uploadMany = (req, res) => {
  const files = req.files;
  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>

 

 

 


업로드하는 곳이 각각 다를때

<form method="post" action="/upload3" enctype="multipart/form-data">
    <input type="text" name="subject">
    <input type="file" name="upload1" multiple>
    <input type="file" name="upload2" multiple>
    <input type="file" name="upload3" multiple>
    <input type="file" name="upload4" multiple>
    <input type="submit" value="전송">
</form>
app.get('/uploads',(req,res)=>{
    res.render('uploads')
})

//여러개의 파일을 받는 형태
app.post('/upload3', upload.fields([{name:'upload1'},{name:'upload2'},{name:'upload3'},{name:'upload4'}]), (req,res)=>{
    console.log(req.files.upload1)
    console.log(req.files.upload2)
    console.log(req.files.upload3)
    console.log(req.files.upload4)
    console.log(req.body)
    res.send('upload')
})

댓글