- 요청과 응답 사이에서 중간다리 역할을 하는 소프트웨어
- view, static, bodyparser, multer 등이 있다
- multer는 파일업로드를 위한 미들웨어로 npm install multer명령을 통해 모듈 설치가 필요하다
- 프론트단에서 어떤 파일 형태로 보여질지를 결정하는 것이다.
- 확장자 view engine과 view 파일 위치인 views를 app.set을 통해 설정한다
- 강의에서 사용하는 ejs(html과 가장유사)외에도 pug, nunjucks 등이 있다
app.set('view engine', 'ejs');
app.set('views', './views')
- 이미지, 동영상, css등의 정적 요소들을 불러오는 설정이다
- 서버관련 정보는 외부에서 확인 불가능하기 때문에 외부(브라우저)에서 접근 가능한 폴더를 따로 설정하여 사용할 수 있게 해주는 것이다
- app.use()를 사용하여 정의한다
- 외부에서 사용시 가상경로 이름으로 사용해야 불러오기 가능
//여러개 정의 가능
//("가상경로이름",express.staic(현재위치+"진짜경로"))
app.use("/static",express.staic(__dirname+"/public"));
app.use("/uploads",express.staic(__dirname+"/uploads"));
- req.body를 사용할 수 있게 파싱(parsing)해주는 미들웨어
- express내장 모듈로 설치가 필요없다.
- app.use를 사용하여 정의한다
//true= queryString 모듈, false= qs모듈(보안성능만 추가됨)
app.use(express.urlencoded({extended: false}));
//요청 body에서 내가 필요한 객체 정보만 추출할 수 있도록 도와줌
app.use(express.json());
- 파일업로드를 위한 미들웨어
- strage: 저장공간에 대한 정보
1. diskStorage: 파일을 저장하기 위한 모든 제어기능 제공
(1) destination: 저장경로
(2) filename: 파일이름 관련 정보
- limits: 파일제한 관련 정보
1. fileSize: 파일사이즈를 바이트 단위로 제한
- dest vs destination: dest: "폴더이름/"은 선언과 함께 폴더를 자동으로 생성해준다 destination은 폴더를 직접 생성하고 설정해주어야한다
const uploadDetail = multer({
storage: multer.diskStorage({
//request, file정보, callback함수 순으로 세가지 인자가 들어간다
//destination(인자) {} 이런 표현도 가능
destination: function (req, file, cd) {
cd(null, "uploads/");
},
filename: function (req, file, done) {
//확장자를 가져오는 path.extname설정(require필요)
const extension = path.extname(file.originalname); //밑에서 확인한 req.file의 originalname에서 확장자를 추출해요!
done(
null,
//basename(file.originalname, extension) extension을 제외한 (jpg앞의 이름만 가져온다)
path.basename(file.originalname, extension) + Date.now() + extension
); //이름 중복될 경우가 있어서 임의의 밀리초 숫자를 추가로 붙여준다
},
}),
//파일크기 제한 5기가바이트로 설정(참고만)
limits: { fileSize: 5 * 1024 * 1024 },
});
- multer를 설치해주고
- const multer = require('multer');
- const path = require('path');
- path는 multer에서 파일 위치 정보를 통해 이름을 추출할때 사용된다
- input type = file 태그에 name속성 반드시 적어준다
- form의 method는 반드시!!!! post로 지정한다
- 기존 라우팅 방식과 달리 두번째 인자로 파일 업로드에 관한 매개변수를 추가해야한다
- 위에서 설정한 multer관련 변수.메소드('name')로 접근한다
- single: 하나의 파일 업로드 시 사용, 객체로 파일 정보가 온다, req.file로 접근
- array: 여러 파일 업로드 시 사용, input태그에 multiple키워드를 추가해주면 작동, 배열안의 객체[{}]형태로 데이터 날아온다, req.files로 접근
- fields: 여러개의 input에 하나씩 파일업로드하여 한번에 가져오는 경우, fields메소드([{name: name1}, {name: name2}, {name: name3}]), req.files로 접근
- post요청을 받아 url로 정보를 보낼때 어떤 형태로 보내야 할지 모르겠다면 console.log()를 통해 받은 요청데이터를 확인해보자
- view에서 업로드된 파일의 src를 받아야한다면 req.file.path데이터를 활용할 수 있다
//다른 input text, password등 body정보와 함께 보낼수도 있다
res.send({
title: req.body,
fileInfo: req.file,
});
- form태그 없이 동적파일 업로드를 진행해보았다(cdn잊지말기)
- type="button"에 onclick이벤트 함수를 걸어 해당 함수 내부에 Axios메소드를 사용하였다
- js에 기본 정의된 FormData() 클래스를 사용하여 임의의 form객체를 생성하고 사용한다
- input file 요소와 업로드한 파일을 표시할 img 태그를 const로 정의하여 사용한다
- FormData() 클래스를 사용하여 생성된 form객체에 append를 통해 file의 정보를 가지는 input 자식요소를 추가한다
- axios를 이용하여 formdata를 전송하고(post) 라우팅(방식 위와 동일) 이후 then()에서 데이터를 받아 img변수의 src에 값을 지정해주면 완료된다
- file외에 다른 input값과 함께 전송할 경우 해당 값도 append를 사용하여 임의의 form객체에 추가해주면 된다
//위의 설명대로 진행한 예시코드 app.js는 생략함
function fileUpload() {
const file = document.getElementById("dynamicFile");
const img = document.querySelector(".profile");
const formData = new FormData();
console.log(file);
console.dir(file); //트리(객체)형태로 콘솔창에 나온다
console.log(file.files[0]); //배열로 파일정보가져옴
formData.append("dynamicFile", file.files[0]);
//form객체에 <input name="dynamicFile" value=file.files[0]>요소가 생성됨
//formData.append('name', value)
axios({
method: "post",
url: "/dynamicUpload",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
}).then((res) => {
console.log(res);
console.log(res.data); //파일과 관련된 정보가 있을 거임
console.log(res.data.path); //업로드된 이미지 정보 src에 들어갈 정보!
//img태그에 업로드한 사진 올리기
img.src = res.data.path;
});
}
- query와 다른 url에 값 넣는 방식이다
- server: /:params
- client: /123
- req.params를 통해 값을 확인할 수 있다 {params: '123'}
//예시코드 -> 클릭시 a태그의 link로 contentID의 값을 받아 실행
app.get("/content/:contentID", (req, res) => {
console.log(req.params);
//{ contentID: '3' } 출력
//req.params.contentID의 값을 저장한다
const { contentID } = req.params; //객체분할할당
//실제 tempDB의 값과 params로 들어온 값을 비교
const isContent = tempDB.filter(
(obj) => obj.contentID === Number(contentID)
)[0];
console.log(isContent); // {} or undefined
//{}이면 if문이 실행
if (isContent) {
res.render("content", isContent);
} else {
//undefined면 else가 실행된다
res.render("404");
}
});
- form method 종류, form의 데이터를 삭제한다
- 강의에서는 버튼 클릭시 작동하는 이벤트 함수를 설정하고 contentID를 매개변수로 받아 aixos로 삭제를 진행하였다
- axios메소드의 url로 쿼리문("xxx?contentID=" + contentID)을 통해 데이터를 server로 전송하였다
- delete명령은 별다른 응답 데이터가 필요없기 때문에 then()은 생략해주었다
axios({
method: "delete",
url: "/blog/delete?contentID=" + contentID, //query로 처리
}).catch((err) => {
//데이터 받아서 할 작업 없으므로 then생략
console.error(err);
});
***
//server에서
app.delete("/blog/delete", (req, res) => {
console.log(req.query); //contentID값이 들어온다
const { contentID } = req.query; //객체구조분해할당
//filter() 조건에 맞는 애들만 모아서 배열로 반환
tempDB = tempDB.filter((obj) => obj.contentID !== Number(contentID)); //삭제로 온 id값이 아닌 애들만 반환
console.log(tempDB); //확인
res.end(); //별다른 반환없이 그냥 끝내도 된다
});
- res.render()나 res.send() 대신 사용할 수 있다
- ('url') 해당 url로 이동한다
res.redirect("/");