⚒️ 오늘 할 실습
로그인을 한 후 자신의 프로필을 바꿀 수 있는 설정이 있다. 오늘은 이 프로필을 설정하는 방법에 대해 배울 것이다.
사실 현재는 백엔드와의 통신을 하는 것으로 끝이나 이후에 db와도 연동해서 할 계획이다.
이미지 파일을 올리기 위해서는 multer라는 미들웨어가 필요하다. (대중적으로 가장 많이 쓰인다고 하셨다.)
😮 그전에!
기본에는 데이터만 보냈기 때문에 body-parser만 썼다.
//body-parser
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
하지만 body-parser는 이미지, 동영상, 파일 등을 보낼 수 없다는 단점이 있기 때문에 이번 시간에 보낼 이미지를 보내기 위해서는 또 다른 미들웨어가 필요하다.
그게 바로 이번에 배울 multer이다.
그전에 이미지를 넣을 정적 파일을 설정해 줘야 한다. 클라이언트에서 이미지를 보내면 이 파일에 들어갈 것이다.
// 정적파일 생성
app.use("/uploads", express.static(__dirname + "/uploads"));
uploads라는 폴더를 생성 후 위의 코드를 써주면 된다.
🗂️ multer 사용법
이제 진짜 multer 사용법에 대해 알아볼 것이다.
multer 패키지 안에는 파일 저장 관련 설정을 해주는 storage객체와 파일 크기를 제한해주는 limits객체가 존재한다.
const storage = multer.diskStorage({
// destination: 저장될 경로 지정(요청객체, 업로드된 파일객체, 콜백함수)
destination: (req, file, cb) => {
cb(null, "uploads/"); // uploads 폴더에 저장
},
// filename: 파일 이름결정(요청객체, 업로드된 파일객체, 콜백함수)
filename: (req, file, cb) => {
// extname: 확장자를 추출
const ext = path.extname(file.originalname);
// basename : 파일이름 추출(파일이름,확장자) => 확장자를 제외해서 파일이름 추출
const newName = path.basename(file.originalname, ext) + Date.now() + ext; //basename + 오늘 날짜(겹치지 않게 하기 위해) + 확장자
cb(null, newName);
},
});
먼저 storage는 multer의 diskStorage를 불러와서 설정한다. 이 안에는 저장될 경로와 저장할 파일의 이름을 지정해 준다.
destination : 파일이 저장될 공간
filename : 파일이 저장될 때의 이름 설정
콜백함수의 첫 번째 인자는 에러 객체이고, 두 번째 인수는 결괏값이다. 에러가 발생하지 않았을 경우에는 첫 번째 인수에 'null'값을 전달하여 에러가 없음을 나타내고, 두 번째 인수에는 원하는 결괏값을 전달한다.
// 파일 크기 제한
const limits = {
fileSize: 5 * 1024 * 1024, // 5MB
};
파일 크기는 간단하게 적을 수 있다. 나는 5MB로 지정해 줬다.
이렇게 만든 변수들을 이젠 multer 객체에 넣을 것이다.
// key-value에서 key값과 value의 변수가 동일 하면 합칠 수 있음
const upload = multer({ storage, limits });
multer객체를 생성 후 storage: storage, limits:limits로 해준다. 이때 key와 value의 값이 동일하면 합칠 수 있다는 것을 알아두자!!
파일을 올리는 방법에는 총 3가지가 있다.
밑줄 친 부분만 달라지기 때문에 주의해서 보면 좋을 거 같다.
또 주의할 점은 노란색으로 칠 해진 부분은 프런트의 input=file 부분의 name과 일치시켜줘야 한다. (필수)
1️⃣ 하나의 파일만 올리기
2️⃣ 한 번에 여러 개의 파일 올리기
한번에 올릴 수 있는 최대 개수를 지정해 줄 수 있다.
3️⃣ 하나의 폼 안에 여러개의 파일 올리기
하나의 폼 안에 여러 개의 파일을 올릴 때는 배열 형식으로 보내준다. name에는 위에도 말했다시피 프런트의 input=file의 name과 일치 시켜줘야 한다. 그리고 각각에 한번에 올릴 수 있는 최대 개수도 지정해 줄 수 있다.
📖 실습하기
비동기 방식으로 여러개의 이미지 파일을 주고받는 과정을 해보겠다.
🖥️ 프런트
<h1>파일 여러개 올리기</h1>
<form onsubmit="fileupload(event)">
<input type="file" id="dynamic" multiple><br>
<input type="text" id="title"><br>
<button type="submit">업로드하기</button>
</form>
<div class="result"></div>
이번에는 form의 onsubmit 방식을 사용해서 백엔드에 전송할 것이다.
여러 개의 파일을 올릴 때는 해당 input 태그에 multiple이라는 명령어를 써주자.
event.preventDefault(); // onsubmit() 함수가 새로 고침되는 것을 막아준다.
const title = document.querySelector("#title").value;
const file = document.querySelector("#dynamic");
// 폼 데이터 생성
const formData = new FormData();
// 폼 데이터에 제목 추가
formData.append("title", title)
// 추가한 파일의 수만큼 폼 데이터에 추가한다.
for (let i = 0; i < file.files.length; i++) {
formData.append("dynamic", file.files[i])
}
event.preventDefault()를 가장 위에 쓰는 이유는 페이지가 새로고침되는 것을 막기 위해서다. 폼 안에 onsubmit 함수는 폼 안의 내용을 백엔드로 보내주고 새로고침 되도록 설정되어 있다. 만약 event.preventDefault()를 쓰지 않는다면 어떠한 값도 백엔드로 넘어가지 않을 것이다.
이후 추가한 파일의 수만큼 폼 데이터에 추가해 줘야 한다.
그러기 위해서는 for문을 통해 파일의 수 만큼 반복해줘야 한다. 그렇다면 file.files는 뭘까?
file.files를 콘솔로 찍은 모습이다. 2개의 파일을 추가했기 때문에 길이가 2인 배열이 나오는 것을 볼 수 있다.
이젠 이 값을 백엔드로 보낼 것이다.
axios({
method: "post",
url: "/dynamic",
data: formData,
headers: {
"Content-Type": "multipart/form-data"
}
}).then(res => {
console.log("res", res)
})
헤더에는 필수로 Content-Type을 명시해줘야 한다.
백엔드에서 req.files로 받으면
이런 값이 나오는데 이 값들을 가지고 프론트에 이미지를 띄어주거나 조작할 수 있다.
uploads 폴더에도 잘 들어간 것을 볼 수 있다.
'포스코x코딩온' 카테고리의 다른 글
[포스코x코딩온] 웹개발자 풀스택 과정 6주차 회고록 - Mysql과 연동하여 비동기 통신하기(1) - Mysql 설치 및 사용법 (0) | 2023.08.15 |
---|---|
[포스코x코딩온] 웹개발자 풀스택 과정 9기 5주차 회고록 - MVC 구조 (0) | 2023.08.11 |
[포스코x코딩온] 웹개발자 풀스택 과정 5주차 회고록 - 동적 Form 전송(Axios - 비동기 HTTP 통신) (0) | 2023.08.07 |
[포스코x코딩온] 웹개발자 풀스택 과정 5주차 회고록 - 정적 Form 전송(동기 HTTP 통신) (0) | 2023.08.06 |
[포스코x코딩온] 웹개발자 풀스택 과정 4주차 회고록 - Express, EJS (0) | 2023.08.03 |