본격적인 파일 업로드 기능 사용해보기.
이전에 해보았던 Day.11 - 파일 업로드와 동일한데 차이점은 라우터를 사용해서 좀더 express적인 방식으로 코드가 변경 되었다.
app.get / app.post를 쓰면되는데 굳이 왜 라우터를 쓸까?
router를 사용하게되면, 많아지는 HTTP 요청 작업에 대해서 소스코드의 정리가 가능해진다.
router폴더를 하나 새로 만들어 해당 폴더에 HTTP 요청을 넣음으로써, 모듈화할 수 있다는 장점이 있다.
자세한 이유는 여기에 잘 나와있다.
const express = require("express");
const app = express();
const router = express.Router();
// 여러개 파일 업로드를 위한 multer
const multer = require("multer");
//라우터를 미들웨어로 사용.
app.use("/", router);
express 서버를 쓸 것이고, 이번에는 router를 이용할 것이므로 Router객체 또한 선언해준다.
💛 5번에서 쓰인다.
이후 라우터를 미들웨어로 사용하도록 하여, 해당 서버로 보내는 모든 "/"로 시작되는 요청은 router로 전달되게 된다.
서버의 html 파일 및 서버로 올린 파일이 저장될 폴더인 uploads에 접근이 가능해야한다.
따라서 다음과 같이 정적 폴더/파일에 접근이 가능하도록 해주자.
app.use(express.static(__dirname + "/public"));
app.use(express.static(__dirname + "/uploads"));
위과 같이 전체 디렉토리 명을 절대경로를 통해 지정해 주어도 되고, server.js
파일과 동일 선상에 디렉토리가 위치한다면 아래와 같이 간단하게 써도 된다.
app.use(express.static("public"));
app.use(express.static("uploads"));
multer는 여러 기능을 제공하는데 그 중 하나는diskStorage는 로컬의 저장소에 파일을 저장할 수 있도록 해준다.
이를 통해 diskStorage
를 생성하도록 하자.
let diskStorage = multer.diskStorage({
// 목적지 주소
destination: function(req, file, callback){
callback(null, "upload");
},
// 저장될 파일 이름
filename: function(req, file, callback){
callback(null, Date.now() + file.originalname);
}
});
diskStorage를 통해서 저장할 저장소 storage
객체를 만드는 부분이다.
이러한 저장소 객체에는 저장이 될 목적지 주소와 파일의 이름이 포함되어야 한다.
|3| 번에서 만든 diskStorage
를 이용해서 multer를 생성하도록 하자.
앞전 맨 처음에 나온 const multer = require("multer");
이 부분은 단지 모듈을 불러 왔을 뿐이고, 이를 이용해서 storage 및 파일의 형식을 추가한 진짜 multer를 생성한다고 생각하면 된다.
let upload = multer({
// 이전 생성한 diskStorage객체를 사용
storage: diskStorage,
// 최대 파일의 개수는 10개, 크기는 1GB
limit : {
files : 10,
fileSize : 1024 * 1024 * 1024
}
})
upload라고 선언한, Multer 객체이다.
라우터는 클라이언트로부터 요청을 받는 부분이므로 클라이언트와 서버 부분을 나눠서 보도록하자.
|4|번에서 생성한 multer(upload)를 통해서 클라이언트로부터 요청을 받을 라우터이다.
router.route("/process/photo").post(upload.array("MyfileName", 1), (req, res)=>{
res.end("filed uploaded");
})
/process/photo로 요청되는 Post 메소드를 받으며, 해당 요청이 들어오게되면 upload.array()가 수행된다.
upload.array()함수는 아래와 같은 형태를 가진다.
multer.array(fileName[, maxCount])
- filedname 인자에 명시된 이름의 파일 전부를 배열 형태로 전달 받는다.
- 여기서 fileName은 MyfileName 형태로 클라이언트에서 전달해 주고 있다.
(아래 클라이언트 코드 참고)
배열 형태로 값을 전달 받을 때 이러한 array를 호출한 multer에 정의된 diskStorage에 저장되게 된다.
(확실하게 어떤 순서로 동작하는지는 잘 모르겠다)
클라이언트(HTML) 쪽은 다음과 같다.
<body>
<h1>파일 업로드</h1>
<br>
<form action="/process/photo" method="post" enctype="multipart/form-data">
<input type="file" name="MyfileName">
</br>
<input type="submit" value="업로드 하기">
</form>
</body>
파일을 전송할 수 있도록 multipart/form-data
형태로 사용하고 있다.
또한 전송되는 file의 Name이 MyfileName으로 하여 전송되고 있다. (따라서 위 서버 부분에서 받을 때 MyfileName으로 받고 있다.)
이렇게 라우터로의 POST 요청이 가능한 이유는 |1|번에서 라우터를 미들웨어로 사용하도록 app.use("/", router);
를 선언하였기 때문이다.
app.listen(3000, () => {
console.log("Node.js 서버 실행 중 ... http://localhost:" + 3000);
});
다음과 같이 app.listen을 통하여 서버를 실행시키는 코드를 작성하고, npm start를 통해 서버를 작동시켜 보도록 하자.
끝!
다음과 같이 에러가 발생했을 때의 페이지가 출력되도록 할 수 있다.
여기서는 404 에러가 발생했을 때, public 폴더 내에 있는 404.html가 출력되도록 하였다.
/////// error handler -----
var expressErrorHandler = require('express-error-handler');
var errorHandler = expressErrorHandler({
static : {
'404':'./public/404.html'
}
});
app.use(expressErrorHandler.httpError(404) );
app.use(errorHandler );
<!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>Error Page</h1>
</body>
</html>
쿠키와 함께 사용되며 세션을 생성하는데 사용된다.
cookieParser란 요청을 보낼 때 함꼐 들어온 쿠키를 파싱해 사용할 수 있도록 해주는 모듈이다.
위 두 모듈은 로그인 관련에서 사용된다.