파일 다루는 방식을 한번 정리해보고 싶어서 블로그를 작성해본다.
파일 업로드는 일단 Multer라는 모듈을 사용할 것이다. Multer는 파일 업로드를 위해 사용되는 multipart/form-data 를 다루기 위한 node.js 의 미들웨어이다.
Multer Reference를 참고해보자.
https://github.com/expressjs/multer/blob/master/doc/README-ko.md
GitHub - expressjs/multer: Node.js middleware for handling `multipart/form-data`.
Node.js middleware for handling `multipart/form-data`. - GitHub - expressjs/multer: Node.js middleware for handling `multipart/form-data`.
github.com
multer 설치
npm install --save multer
이제 multer를 사용 할 수 있다. 아주 간단한 예제를 만들어보기 앞서
views 하위 폴더에 upload.ejs와 confirmation.ejs 두가지를 생성할 것이다.
upload.ejs는 파일 업로드할 form이 있는 ejs 이고 confirmation.ejs는 파일을 제출할 시 넘어가는 viewer이다.
저장할 폴더만 지정하여 저장하기
upload.ejs
<!DOCTYPE html>
<html>
<head>
<title>Multer 예제</title>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' />
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<div class="container">
<h3>1.싱글파일, input text 업로드</h3><br/>
<form class="row g-3" action="/uploadFile" enctype="multipart/form-data" method="post">
<div class="mb-3 row">
<label for="title" class="col-sm-2 col-form-label">제목</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="title" >
</div>
</div>
<div class="mb-3 row">
<label for="content" class="col-sm-2 col-form-label">내용</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="content">
</div>
</div>
<div class="mb-3 row">
<label for="file" class="col-sm-2 col-form-label">파일 첨부</label>
<div class="col-sm-10">
<input type="file" class="form-control" name="attachment">
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-3">제출</button>
</div>
</form>
</body>
</html>
빠른 작성을 위해 bootstrap을 사용했다. 제목과 내용, 파일을 작성하는 form이다.
confirmation.ejs
<!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>Success!</h1>
제목 : <%= title %>
<br>
내용 : <%= content %>
<% if(file){ %>
<pre><%=JSON.stringify(file, null, 2)%></pre>
<% }%>
<a href='/'>Back</a>
</body>
</html>
폼 제출 성공시, 보여지는 화면이다. 제목과 내용, json 형태로 된 file의 정보를 보여준다.
routes/index.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
let upload = multer({ dest: 'uploadedFiles/' }); // 파일이 저장될 폴더 설정, 기본 multer
router.get('/', function(req,res){
res.render('upload');
});
router.post('/uploadFile', upload.single('attachment'), function(req,res){
res.render('confirmation', { file:req.file, title: req.body.title, content: req.body.content});
});
module.exports = router;
var multer = require('multer')를 이용하여 multer모듈을 사용한다는 것을 명시하고
upload라는 변수에 파일이 저장될 폴더만 지정해두었다. uploadFile에 저장하라고 명시해두었다.
결과값
이렇게 제목, 내용, 파일첨부를 선택하고 제출을 누르면
내용이 잘 전달됨을 볼 수 있다. uploadFile도 살펴보면
알수없는 이름의 파일이 저장되었다. 이 파일의 이름에 끝에 원래 확장자를 넣으면 첨부한 파일이 옳게 저장되었는지 확인해 볼 수 있다.
이렇듯, 파일 이름을 무작위로 생성되는게 아닌, 사용자가 지정하고 싶다면 multer.DiskStorage를 사용한다.
DiskStorage는 파일을 디스크에 저장하기 위한 모든 제어 기능을 제공한다.
파일 이름 변경하여 저장하기
routes/index.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var storage = multer.diskStorage({
destination(req, file, cb) { // 파일이 저장된 폴더
cb(null, 'uploadedFiles/');
},
filename(req, file, cb) { // destination 에 저장된 파일 명
cb(null, `${Date.now()}__${file.originalname}`);
},
});
// let upload = multer({ dest: 'uploadedFiles/' });
let uploadWithOriginalFilename = multer({ storage: storage }); // 파일 명이 지정된 형식으로 변함
router.get('/', function(req,res){
res.render('upload');
});
router.post('/uploadFileWithOriginalFilename', uploadWithOriginalFilename.single('attachment'), function(req,res){
res.render('confirmation', { file:req.file, files:null });
});
module.exports = router;
diskStorage를 통해 파일 이름을 현재 날짜_파일의 원래 이름으로 지정해주었다.
upload.ejs
<!DOCTYPE html>
<html>
<head>
<title>Multer 예제</title>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' />
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<div class="container">
<h3>2. 싱글파일 업로드 (파일이름 유지))</h3><br/>
<form action="/uploadFileWithOriginalFilename" enctype="multipart/form-data" method="post">
<input type="file" name="attachment">
<button type="submit" class="btn btn-primary">제출</button>
</form>
<hr>
</div>
</body>
</html>
confirmation.ejs
<!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>Success!</h1>
<% if(file){ %>
<pre><%=JSON.stringify(file, null, 2)%></pre>
<% }%>
<a href='/'>Back</a>
</body>
</html>
결과값
상훈이형.jpg 이라는 파일을 제출하였다.
filename에 1643000956034__상훈이형.jpg 라고 변경됨을 알 수 있다.
폴더에 지정한 파일 또한 잘 저장됨을 알 수 있다.
여러 파일 업로드
여러 파일을 업로드할때는 upload.single() 대신에 upload.array()를 사용한다.
주의할 점은 ejs에서 파일을 여러개 보낼 때는 <input type="file" multiple> multiple을 작성해 주는 것을 잊지 말자.
또한 파일을 하나만 보내면 req.file로 받으면 되는데 파일을 여러개 보내면 req.files로 받아야 한다.
routes/index.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var storage = multer.diskStorage({
destination(req, file, cb) { // 파일이 저장된 폴더
cb(null, 'uploadedFiles/');
},
filename(req, file, cb) { // destination 에 저장된 파일 명
cb(null, `${Date.now()}__${file.originalname}`);
},
});
// enctype="multipart/form-data" 처음에는 텍스트만 하니까 안가졌는데 multer를 라우터 선언할 때 같이 선언하니까 됐다
let upload = multer({ dest: 'uploadedFiles/' }); // 파일이 저장될 폴더 설정, 기본 multer 세팅. 이름을 지정해주지 않아서 무작위로 변함
let uploadWithOriginalFilename = multer({ storage: storage }); // 파일 명이 지정된 형식으로 변함
router.get('/', function(req,res){
res.render('upload');
});
router.post('/uploadFiles', upload.array('attachments'), function(req,res){
res.render('confirmation', { file: null, files:req.files});
});
router.post('/uploadFilesWithOriginalFilename', uploadWithOriginalFilename.array('attachments'), function(req,res){
res.render('confirmation', { file:null, files:req.files });
});
module.exports = router;
파일 이름이 무작위로 바뀌는 것과 파일 이름을 지정할 수 있는 두가지로 구현을 해보았다.
upload.ejs
<!DOCTYPE html>
<html>
<head>
<title>Multer 예제</title>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' />
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<div class="container">
<h3>3. 여러 파일 업로드</h3><br/>
<form action="/uploadFiles" enctype="multipart/form-data" method="post">
<input type="file" name="attachments" multiple>
<button type="submit" class="btn btn-primary">제출</button>
</form>
<hr>
<h3>4. 여러 파일 업로드 (파일이름 유지)</h3><br/>
<form action="/uploadFilesWithOriginalFilename" enctype="multipart/form-data" method="post">
<input type="file" name="attachments" multiple>
<button type="submit" class="btn btn-primary">제출</button>
</form>
</div>
</body>
</html>
confirmation.ejs
<!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>Success!</h1>
<% if(files){ %>
<pre><%=JSON.stringify(files, null, 2)%></pre>
<% }%>
<a href='/'>Back</a>
</body>
</html>
결과값
제발 그만해.jpg와 상훈이형.jpg를 선택한 뒤 제출을 클릭하면
두개 파일의 json array가 잘 출력됨을 볼 수 있고
파일 업로드도 잘 됐음을 볼 수 있다.
다음시간에는 파일을 업로드하고 업로드한 파일의 섬네일을 보고 파일을 db에 저장하고 또 가져오는것 까지 해볼것이다.
너무길면 나눠서 잘라서 구현해볼 것이다.
Reference
https://github.com/datoybi/blog-posting/tree/main/multer-file-storage
GitHub - datoybi/blog-posting: code examples posted on my blog
code examples posted on my blog. Contribute to datoybi/blog-posting development by creating an account on GitHub.
github.com
'개발 > Node.js' 카테고리의 다른 글
[nodejs] 오류 처리 미들웨어 사용법 (비동기) (0) | 2022.01.19 |
---|---|
[nodejs] Middleware 미들웨어 개념, 종류, 사용법(에플리케이션 레벨 미들웨어, 라우터 레벨 미들웨어) 1 (0) | 2022.01.17 |
nodejs를 이용한 페이징 처리 (DB 연결) Step3 (0) | 2021.11.22 |
nodejs를 이용한 페이징 처리 (페이징 버튼 처리) Step2 (0) | 2021.11.22 |
nodejs를 이용한 페이징 처리 (버튼 누를시 게시글 갱신) Step1 (0) | 2021.11.16 |