Node.js - express (18) multer (2)

2022. 3. 15. 21:58·Node/Express
반응형

 

 

이번 포스팅에서는 파일업로드 창이 여러개일 때 multer를 사용해서 해당 이슈를 해결하는 방법과 비동기 파일 업로드에 대해 다뤄보려고 한다. 이전에 작성한 multer(1)과 이어지는 글이므로 기본적인 세팅법과 메인 서버 파일인 server.js 파일의 내용은 아래 글을 참고하도록 하자.

2022.03.15 - [Node.js/express] - Node.js - express (17) multer (1)

 

Node.js - express (17) multer (1)

이번 포스팅에서는 파일업로드에 사용되는 라이브러리인 multer에 대해 알아보고자 한다. multer를 사용해서 이미지 파일들을 업로드 해보도록 하자. < 목차 > multer 세팅하기 single 파일 업로드 multip

bitkunst.tistory.com

 

 

< 목차 >

  1. 파일 업로드 창이 여러개일 때
  2. 비동기 파일 업로드

 

 

 

1. 파일 업로드 창이 여러개일 때 

우선 저번 포스팅에서 사용한 single.html 파일과 server.js 파일은 아래와 같다.

<!-- single.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Hello multer!!</h1>

    <form method="post" action="/upload" enctype="multipart/form-data">
        <input type="text" name="subject">
        <input type="file" name="upload">
        <input type="submit" value="전송">
    </form>
    
</body>
</html>
// server.js

const express = require('express')
const nunjucks = require('nunjucks')
const app = express()
const multer = require('multer')
const path = require('path')

const upload = multer({
    storage: multer.diskStorage({
        destination: (req, file, done)=>{

            done(null, 'uploads/')
            // 첫번째 인자값은 에러처리에 대한 부분
            // 두번째 인자값은 파일이 저장 될 디렉토리
        },
        filename: (req, file, done)=>{
            const ext = path.extname(file.originalname)
            const filename = path.basename(file.originalname, ext) + '_' + Date.now() + ext
            done(null, filename)
            // 첫번째 인자값은 에러처리에 대한 부분
            // 두번째 인자값은 실제로 저장할 파일명
        }
    }),
    limits: { fileSize: 5*1024*1024 }
})

app.set('view engine', 'html')
nunjucks.configure('./views', {
    express: app,
    watch: true
})

app.get('/single', (req, res)=>{
    res.render('single.html')
})

app.post('/upload', upload.single('upload'), (req, res)=>{
    // upload.single() 미들웨어가 req.file을 만들어준다.
    // req.file에 파일에 대한 데이터가 담긴다. 
    console.log(req.file)
    console.log(req.body)
    res.send('uploaded')
})

app.listen(3000, ()=>{
    console.log('server onload')
})

single.html 에 있는 파일 업로드 input 박스는 한번에 하나의 파일만을 업로드 할 수 있는 형태이다. 다음과 같이 여러개의 input 박스를 만들어서 하나의 <form>엘리먼트 안에 여러개의 파일 업로드 창이 존재할 경우 server.js 파일에서는 어떠한 미들웨어를 사용해야 하는지 알아보도록 하자.

<form method="post" action="/upload3" enctype="multipart/form-data">
    <input type="text" name="subject">
    <input type="file" name="upload1">
    <input type="file" name="upload2">
    <input type="file" name="upload3">
    <input type="file" name="upload4">
    <input type="submit" value="전송">
</form>

서로 다른 name값을 갖고 있는 여러개의 input 박스들이 method="post" action="/upload3" 속성을 갖고 있는 하나의 <form>엘리먼트 안에 존재하고 있는 상황이다. 해당 경우에는 server.js 파일 안에 다음과 같은 app.post( ) 라우터를 만들어주면 된다.  

// 파일 업로드 input 박스가 여러개일 때
app.post('/upload3', upload.fields([{name: 'upload1'}, {name: 'upload2'}, {name: 'upload3'}, {name: 'upload4'}]), (req, res)=>{
    // upload.fields() 미들웨어 사용
    // req.files.[name]에 파일에 대한 정보가 담긴다.
    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('uploaded')
})

 

파일 업로드 input 박스가 여러개일 경우에는 upload.fields( ) 미들웨어를 사용한다. 해당 미들웨어의 인자값으로는 배열이 들어가게 되는데 이 배열 안에는 각각의 input 박스의 name값이 객체 형태로 들어간다. 업로드 된 파일의 정보들은 req.files.upload1 , req.files.upload2 ... 와 같이 req.files.[name값] 안에 담기게 된다.  

 

이전에 살펴본 내용들과 함께 미들웨어를 정리해보면 다음과 같다.

  • single 파일 업로드  :  upload.single( 'input 박스의 name값' )
  • multiple 파일 업로드  :  upload.array( 'input 박스의 name값' )
  • 하나의 form 엘리먼트 안에 여러개의 파일 업로드 input 박스  :  upload.fields( [ { name: ' ' }, { name: ' ' }, ... ] )

 

 

2. 비동기 파일 업로드 

이번에는 axios를 사용해서 비동기 방식으로 파일 업로드를 진행해보려고 한다. axios.html 파일을 새로 만들어서 다음과 같이 <script>를 작성해주도록 하자.

<!-- axios.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
    <h1>Hello Asyncronous multer!!</h1>
    <form method="post" action="/upload" enctype="multipart/form-data">
        <input type="text" name="subject">
        <input type="file" name="upload">
        <input type="submit" value="전송">
    </form>
    <script type="text/javascript">
        const frm = document.querySelector('form')
        frm.addEventListener('submit', async (e)=>{
            e.preventDefault()
            
            // e.target.subject : form 엘리먼트 안에 있는 name="subject"인 input 엘리먼트 
            // e.target.upload  : form 엘리먼트 안에 있는 name="upload"인 input 엘리먼트
            const {subject, upload} = e.target
            
            // upload.files[0]  : 업로드 파일 정보가 담겨져 있는 객체

            // body에 넣을 내용 만들기
            const formData = new FormData()  // enctype에 있는 포맷으로 변환
            formData.append('upload', upload.files[0])
            formData.append('subject', subject.value)
        
            const response = await axios.post('/upload', formData)
        })
    </script>

</body>
</html>

우선 e.preventDefault( )를 통해 'submit' 이벤트를 막아주도록 하자. 그런 다음 e.target.subject 와 e.target.upload를 통해 각각 name="subject" 와 name="upload"인 input 엘리먼트를 가져와서 subject 변수와 upload 변수에 할당한다. 

 

upload.files[0] 을 통해 File 객체를 가져올 수 있는데 File 객체 안에는 업로드 한 파일의 정보들이 담겨있다. FormData( )를 사용하면 File 객체의 내용을 <form>엘리먼트의 enctype에 있는 형태로 치환해줄 수 있다. append( ) 메소드를 이용해 formData 객체 안에 upload.files[0] 데이터를 'upload'라는 이름값으로 , subject.value를 'subject'라는 이름값으로 넣어준다. 이러한 처리를 통해 비동기 요청을 할 때 Request Body에 들어갈 내용들을 만들어 줄 수 있다. 

 

이제 마지막으로 axios.post( '/upload', formData ) 로 요청을 보내주면 된다. ( body 내용을 formData로 전달 )  

해당 요청을 받는 라우터는 기존의 app.post( '/upload' , upload.single('upload') , (req, res)=>{ } ) 라우터를 사용해주면 된다. 

app.get('/axios', (req, res)=>{
    res.render('axios.html')
})

app.post('/upload', upload.single('upload'), (req, res)=>{
    // upload.single() 미들웨어가 req.file을 만들어준다.
    // req.file에 파일에 대한 정보가 담긴다. 
    console.log(req.file)
    console.log(req.body)
    res.send('uploaded')
})

 

 

 

 

 

반응형

'Node > Express' 카테고리의 다른 글

Node.js - express (19) WebSocket  (0) 2022.03.18
Node.js - express (17) multer (1)  (0) 2022.03.15
Node.js - express (16) CORS  (0) 2022.03.13
Node.js - express (15) Ajax - fetch , axios  (0) 2022.03.07
Node.js - express (14) Ajax - XMLHttpRequest( )  (0) 2022.03.06
'Node/Express' 카테고리의 다른 글
  • Node.js - express (19) WebSocket
  • Node.js - express (17) multer (1)
  • Node.js - express (16) CORS
  • Node.js - express (15) Ajax - fetch , axios
bitkunst
bitkunst
Ever tried, Ever failed, No matter. Try again, Fail again, Fail better.
  • bitkunst
    THE DEVELOPER
    bitkunst
  • 전체
    오늘
    어제
  • bitkunst GitHub
    • 분류 전체보기 (154)
      • Setup (1)
      • HTML (7)
      • CSS (10)
      • Go (2)
      • JavaScript (14)
      • TypeScript (3)
      • Node (34)
        • Node.js (7)
        • Express (19)
        • NestJS (8)
      • React (19)
      • MySQL (6)
      • BlockChain (14)
      • Ethereum (20)
      • AWS (5)
      • Linux (2)
      • Infra (2)
        • Docker (2)
      • Testing (2)
      • ABOUT CS (11)
      • 토이 프로젝트 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    nestJS
    nodejs mysql
    타입스크립트로 블록체인 만들기
    AWS
    타입스크립트로 블록 체인 만들기
    React
    웹프론트엔드
    Blockchain
    CSS Style
    Nest
    타입스크립트 블록 체인
    블록체인 지갑 서버 만들기
    자바스크립트
    JavaScript
    웹개발
    이더리움 스마트 컨트랙트
    TypeScript Blockchain
    html
    프론트엔드
    타입스크립트 블록체인 만들기
    리액트
    블록체인
    Nodejs
    AWS EC2
    블록체인 트랜잭션 만들기
    css
    이더리움
    redux
    웹
    Ethereum
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.1
bitkunst
Node.js - express (18) multer (2)
상단으로

티스토리툴바