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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

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

티스토리툴바