생각기록
2022-11-26 미들웨어, 파일 업로드 본문
미들웨어 개념 (Middleware)
1. 서버가 작업하기 전에 사이에 함수를 껴놓을 때 = 미들웨어 함수라고 한다
app.get 로직까지 가기 전에 = 클라이언트의 요청이 서버로 가기전에
사전에 함수로 먼저 검사할 수 있는 것
2. 미들웨어에서는 reques, response 객체를 모두 사용 가능하고!
next() 함수를 이용해 다음 미들웨어로 접근이 가능하다.
중간에 껴있기 때문에 req, res 객체를 다 가지고 있다.
next()함수 : 미들웨어 동작이 끝나면, 원래 가고자 하던 서버 로직으로 가는 것
multer
설치 : npm install multer
모듈 추가 : path와 multer 모듈 객체로 불러와서 써야함
파일의 경로(목적지)를 설정하는 multer 객체 사용
1. 서버의 요청
enctype="multipart/form-data"
enc타입 서버가 어찌 읽을지 정함 => ( multipart문자를 인코딩 하지 않겟다 )
기본적으로 서버가 인코딩하게 됨
BUT 파일같은 경우 인코딩이 진행되면, 깨지니까 이 속성을 반드시 지정해야 한다. ( input 파일 필요 )
<h5>upload.single()</h5>
<form action="/upload-single" method="post" enctype="multipart/form-data">
<!-- 하나는 userfile기준으로 위에는 name, 아래는 name2가 존재한다.
userfile값은 받을 수 있는데 name2는 받을 수 없다
파일이 중간에 껴있으면 파일 이전까지 데이터는 머터가 처리가 가능한데
이후의 데이터는 처리 할 수 없다.
즉 파일보다 이름입력창을 위에 위치 시켜줘야 한다.-->
<input type="text" name="name"><!--multer 미들웨어 처리 o-->
<input type="file" name="userfile">
<input type="text" name="name2"><!--multer 미들웨어 처리 x-->
<button>업로드</button>
</form>
2. 서버의 응답 두 가지
경로 설정만 : 확장자 없이 파일명 자동 설정
const upload = multer ({ dest : " uploads/" });
> 경로에 필요한 폴더도 생성해줘야 함
2. 경로 + 상세 설정 (파일명과 확장자 직접 설정)
multer 인자
1. 어디로?
2. 어떤 이름으로?
const upload = multer({
storage: multer.diskStorage({ //diskStorage 하드디스크에 저장할 때 사용하는 함수
destination(req,file,done){
done( null, 'uploads/')
},
filename(req,file,done){
console.log( "filename : ",req.body);
const ext = path.extname(file.originalname);// file.originalname => 파일 원래 이름.확장자를 불러옴
// path.extname() 함수를 이용해서 확장자만 추출 함
// const filename = Date.now() + ext; // 123213123.jpg 지금날짜 밀리세컨트로 파일이름
const filename = req.body.name + ext; // 머터는 파일보다 늦게 지정된 얘들은 처리 못합니다. 즉 파일에서 처리해야하는 데이터는 파일보다 위에
done( null, filename);
}
})
})
- storage 저장할 공간에 대한 정보. 디스크나 메모리 저장 가능
- diskStorage 하드디스크에 업로드(저장)할 때 사용하는 함수
- destination 저장할 경로
- filename 저장할 파일명 ( 파일명+ 날짜 + 확장자 형식 )
- Limits 파일 개수나 파일 사이즈를 제한 할 수 있음
// file.originalname > 파일 원래 이름.확장자를 불러옴
// path.extname() 함수를 이용해서 확장자만 추출 함
위의 설정이 끝나면,
3. upload의 다양한 미들웨어 설정
- single - 파일을 1개만 업로드
- array - 2개 이상 파일 업로드
- fileds - 1개씩 여러번의 파일 업로드
single
multer 설정에 따라 파일을 업로드 후 req.file 객체가 생성 됨
인수는
- input태그의 name
- 또는 폼데이터의 키와 일치
req.file에 어떤 경로에 저장되어있는지 담아서 전달
업로드가 성공하면, req.body에는 파일이 아닌 input 데이터인 title이 들어감
array
2개 이상의 파일이여서 req.files 사용
inptut 에 multiple 속성을 추가 => 서버에서 upload.arry()로 받게 된다.
fieds
2개 이상의 파일이여서 req.files 사용
input태그나 폼 데이터의 키가 다른 경우 사용
// 1개 파일을 사용할 때는 single() 함수를 사용한다.
// upload.single('userfile')
// <input type="file" name="userfile"> .single('form 의 name과 같아야 한다')
app.post('/upload', upload.single('userfile'), (req, res) => {
console.log(req.file);
console.log(req.body);
res.send('upload complete');
});
// upload.single() 함수는 multer의 내장 함수로 이름을 받아서 업로드까지 하고 next() 함수까지 실행해주는 역할을 한다.
// single() 함수는 1개의 파일만 업로드 할 때 사용한다.
// 2개 이상의 파일을 보내면 array로 받아진다.
// single() 함수 대신에 array 함수를 사용한다.
app.post('/upload-multiple', upload.array('userfile'), (req, res) => {
// 2개 이상의 파일이기 때문에 req.file이 아닌 req.files로 사용한다.
console.log(req.files);
console.log(req.body);
res.send('upload complete multiple');
});
// 1개씩 여러 번의 파일을 업로드하는 경우
// 1개씩 여러번의 파일 업로드를 하는 경우 fields() 함수를 사용하며, list - json 방식으로 받는다.
app.post('/upload-fields', upload.fields([{name: 'userfile1'}, {name: 'userfile2'}, {name: 'userfile3'}]), (req, res) => {
// 2개 이상의 파일이기 때문에 req.file이 아닌 req.files로 사용한다.
console.log(req.files);
console.log(req.body);
res.send('upload complete fields');
});
주의할 점
<h5>upload.single()</h5>
<form action="/upload-single" method="post" enctype="multipart/form-data">
<input type="text" name="name"><!--multer 미들웨어 처리 o-->
<input type="file" name="userfile">
<input type="text" name="name2"><!--multer 미들웨어 처리 x-->
<button>업로드</button>
</form>
userfile기준으로 위에는 name, 아래는 name2가 존재한다.
name2는 받을 수 없다
이유 : 파일이 중간에 껴있으면 파일 이전까지 데이터는 multer가 처리가 가능한데 이후의 데이터는 처리 할 수 없다.
= 즉 input type="file"보다 입력창을 위에 위치 시켜줘야 한다.
실습 1.
일반 폼 전송 사진 업로드
//ejs 파일
<html>
<head>
<title>Practice35-register</title>
</head>
<body>
<form action="/register" target="_blank" method="post" enctype="multipart/form-data">
<fieldset style="width:300px;">
<legend> 개인 정보 </legend>
아이디 : <input type="text" name="id"><br>
비밀번호 : <input type="password" name="pw"><br>
이름 : <input type="text" name="name"><br>
나이 : <input type="text" name="age"><br>
</fieldset>
<input type="file" name="userfile" id="userfile">
<button>회원가입</button>
</form>
</body>
</html>
//서버 파일
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 8000;
app.set("view engine", "ejs");
app.use( "/uploads", express.static( "uploads" ) );
app.use(express.urlencoded({extended: true}));
app.use(express.json());
const upload = multer({
storage: multer.diskStorage({
destination(req,file,done){
done( null, 'uploads/');
},
filename(req,file,done){
const ext = path.extname(file.originalname);
done(null, req.body.id + ext );
}
})
});
app.get("/register", (req,res) => {
res.render("practice35-register");
});
app.post("/register", upload.single("userfile"), (req,res) => {
res.render("practice35-result", { path: req.file.path } );
});
app.listen(port, ()=>{
console.log( "Server Port : ", port );
});
//result.ejs
<html>
<body>
<img src="<%=path%>">
</body>
</html>
실습 2 동적 폼전송
<html>
<head>
<title>Practice35-register</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
function register(){
var form = document.getElementById("form_register");
var formData = new FormData(form);
--------------------------------------------------------------------
// formData를 만들 때 기본값으로 form을 보내면 현재 form에 세팅된 값으로 formData 객체가 만들어진다.
// append를 이용해 하나하나 만들 경우에는 아래 코드처럼 작성해야 한다.
/*
FormData라는 것은 html 에서가 아닌 javascript에서 폼 데이터를 다루기 위해 사용하는 객체
( html 에서는 <form> 태그를 이용해 폼 데이터를 만들 수 있지만, javascript에서는 form 태그를 이용하는 것이 불가능하기 때문에 formData라는 객체를 만들어 사용해야 한다. )
var formData = new FormData();
formData.append('id', form.id.value);
formData.append( key,value ) 라는 문법을 이용할 때 key가 <input name="~~"> 에서 ~~ 가 된다.
즉, 서버에서 req.body 로 받을 때 formData.append 할 때 이용한 key 가 req.body 에 key로 들어가게 된다.
formData.append(key,value) -> req.body에 { key:value } 로 들어간다.
axios({
method: 'post',
url: '~~',
data: { id: '123', pw: 'abcd'}
})
로 전송하는 것을 formData를 이용해서 전송할 때는
var formData = new FormData();
formData.append("id", "123");
formData.append("pw", "abcd");
axios({
method: 'post',
url: '~~',
data: formData
})
로 변경해서 사용할 수 있다.
*/
--------------------------------------------------------------------
axios({
method: "post",
url: "/register2",
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then((a) => { return a.data; })
.then((d) => {
document.querySelector("img").src = d.path;
});
}
</script>
</head>
<body>
<form id="form_register" enctype="multipart/form-data">
<fieldset style="width:300px;">
<legend> 개인 정보 </legend>
아이디 : <input type="text" name="id"><br>
비밀번호 : <input type="password" name="pw"><br>
이름 : <input type="text" name="name"><br>
나이 : <input type="text" name="age"><br>
</fieldset>
<input type="file" name="userfile">
<button type="button" onclick="register();">회원가입</button>
</form>
<br>
<img>
</body>
</html>
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 8000;
app.set("view engine", "ejs");
app.use( "/uploads", express.static( "uploads" ) );
app.use(express.urlencoded({extended: true}));
app.use(express.json());
const upload = multer({
storage: multer.diskStorage({
destination(req,file,done){
done( null, 'uploads/');
},
filename(req,file,done){
const ext = path.extname(file.originalname);
done(null, req.body.id + ext );
}
})
});
app.get("/register2", (req,res) => {
res.render("practice36");
});
app.post("/register2", upload.single("userfile"), (req,res) => {
res.send({ path: req.file.path } );
});
app.listen(port, ()=>{
console.log( "Server Port : ", port );
});
formdata를 만들때
new FromData(form); 에 기본값 (form)을 보내면 현재 form에 셋팅된 값으로 formData 객체가 만들어 진다.
append를 이용해 하나하나 만들 경우
formData는 javaScript에서 폼 데이터를 다루기 위해 사용하는 객체
(html 에서는 <form>태그를 이용해 폼 데이터를 만들 수 있지만, js에서는 form태그를 이용하는 것이 불가능해서 formData객체를 만들어서 사용해야 한다.)
var formData = new FormData();
formData.append('id', form.id.value);
formData.append( key, value ) 라는 문법을 사용할 때
key가 <input name=" ~ " > 에서 ~가 된다.
즉, 서버에서 req.body 로 받을때 formData.append 할 때 이용한 key가 req.body 에 key로 들어가게 된다.
formData.append(key,value) --> req.body에 { key : value } 로 들어간다.
axios({
method: 'post',
url : '~~',
data:{ id : '123', pw : 'abcd' } })
를 ! formData를 이용해서 전송할 때는
var formData = new FormData();
formData.append("id", "123");
formData.append("pw", "abcd");
axios({
method:'post',
url:'~~',
data: formData
})로 사용할 수 있다.
'SeSAC 풀스택 > Nodejs' 카테고리의 다른 글
2022-12-08 Session, Cookie (0) | 2022.12.08 |
---|---|
2022-12-06 sequelize로 방명록, 회원가입 (0) | 2022.12.06 |
2022_11_25_화면 출력 관련 / 참고 사이트 (0) | 2022.11.25 |
2022-11-24 동적 form 전송 (0) | 2022.11.24 |
2022-11-22 Express, ejs 수업 (0) | 2022.11.23 |