간단한 이미지 업로드 서버와 클라이언트를 만들어본다.
서버는 express 사용 및 이미지 업로드를 위해서 middle ware인 multer를 사용한다.
multipart/form-data 형식으로 단일 및 다중 파일 업로드를 지원하기 때문에 가장 많이 사용한다.
※ 멀티파트 형식이란 enctype이 multipart/form-data 인 폼을 통해 업로드하는 데이터의 형식을 의미한다
서버
기본 express 설정
express 설치
npm init -y
npm i express
npm i -D nodemon
server.js 파일 추가
//🏴☠️ server.js
console.log("헬로월드");
nodemon으로 server.js 실행
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"dev": "nodemon server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
기본 express 서버 설정
//🏴☠️ server.js
const express = require("express");
const app = express();
const PORT = 5000;
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
기본 라우터 추가
//🏴☠️ server.js
const express = require("express");
const app = express();
const PORT = 5000;
//라우터 추가
app.post("/upload", (req, res) => {
console.log("/업로드 요청~!");
res.json({ result: "성공~" });
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
post man으로 api 요청 성공
multer로 이미지 업로드 api 만들기
이미지 업로드 플러그인 multer 사용
npm i multer
- https://www.npmjs.com/package/multer
- https://github.com/expressjs/multer/blob/master/doc/README-ko.md (한국어)
지원하는 미들웨어 종류
- storage는 저장할 공간에 대한 정보. 디스크나 메모리 저장 가능.
- diskStorage는 하드디스크에 업로드 파일을 저장한다는 것
- destination은 저장할 경로
- filename은 저장할 파일명(파일명+날짜+확장자 형식)
- Limits는 파일 개수나 파일 사이즈를 제한할 수 있음.
multer 모듈 적용 코드
var multer = require('multer'); // express에 multer모듈 적용 (for 파일업로드)
var upload = multer({ dest: 'uploads/' })
// 입력한 파일이 uploads/ 폴더 내에 저장된다.
// multer라는 모듈이 함수라서 함수에 옵션을 줘서 실행을 시키면, 해당 함수는 미들웨어를 리턴한다.
multer - 저장경로, 파일명 설정
multer 모듈을 통해서 post로 전송된 파일의 저장경로와 파일명 등을 처리하기 위해서는 DiskStorage 엔진이 필요
var multer = require('multer'); // multer모듈 적용 (for 파일업로드)
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/') // cb 콜백함수를 통해 전송된 파일 저장 디렉토리 설정
}
filename: function (req, file, cb) {
cb(null, file.originalname) // cb 콜백함수를 통해 전송된 파일 이름 설정
}
})
var upload = multer({ storage: storage })
express 서버에 적용하기
multer 미들웨어를 통해서 uploads 폴더에 이미지 추가
라우터의 두번째 파라미터에 key 맞춰주기
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const upload = multer({ dest: "uploads" }); //uploads 폴더에 요청한 이미지 저장
const app = express();
const PORT = 5000;
//라우터 추가
app.post("/upload", upload.single("imageTest"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
post man으로 body의 form에 key 맞춰서 요청
uploads 폴더에 요청한 파일 저장 완료
파일 저장 과정 제어를 위해 코드 수정
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) => cb(null, file.originalname),
});
const upload = multer({ storage });
const app = express();
const PORT = 5000;
//라우터 추가
app.post("/upload", upload.single("imageTest"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
업로드한 이미지 이름 고유한 id로 저장하기
uuid 생성
npm i uuid
uuid 사용하기
- filename: (req, file, cb) => cb(null, uuid()) uuid를 추가해주자
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const { v4: uuid } = require("uuid"); //uuid 추가
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) => cb(null, uuid()),//uuid 사용
});
const upload = multer({ storage });
const app = express();
const PORT = 5000;
//라우터 추가
app.post("/upload", upload.single("imageTest"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
uuid를 이용해서 파일 이름 생성
파일 확장자 제어
mime-types 설치
npm i mime-types
.${mime.extension(file.mimetype)} 추가해서 uuid뒤에 파일 확장자 추가
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) =>
cb(null, `${uuid()}.${mime.extension(file.mimetype)}`), //uuid 사용 + 파일 확장자 제어
});
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const { v4: uuid } = require("uuid"); //uuid 추가
const mime = require("mime-types"); //파일 확장자 제어
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) =>
cb(null, `${uuid()}.${mime.extension(file.mimetype)}`), //uuid 사용 + 파일 확장자 제어
});
const upload = multer({ storage });
const app = express();
const PORT = 5000;
//라우터 추가
app.post("/upload", upload.single("imageTest"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
사용자가 업로드한 확장자 이름으로 파일 명 생성
저장한 파일 조회 - static 파일 제공
정적인 파일이 위치할 디렉토리의 이름 선언 (app_file.js)
정적인 파일이 접근할 라우터 path 설정
(express.static 함수를 통해 제공되는 파일에 대한 가상 경로)
app.use('/users', express.static('uploads'));
이를 통해서 /users 경로를 통해 uploads 디렉토리에 포함된 파일을 로드할 수 있음
(ex. http://localhost:3000/users/siwa.png)
app.use(express.static()) 이용해서 외부에 노출 시킬 폴더 지정
app.use("/uploads", express.static("uploads")); //uploads 폴더 외부 노출
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const { v4: uuid } = require("uuid"); //uuid 추가
const mime = require("mime-types"); //파일 확장자 제어
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) =>
cb(null, `${uuid()}.${mime.extension(file.mimetype)}`), //uuid 사용 + 파일 확장자 제어
});
const upload = multer({ storage });
const app = express();
const PORT = 5000;
app.use("/uploads", express.static("uploads")); //uploads 폴더 외부 노출
//라우터 추가
app.post("/upload", upload.single("imageTest"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
localhost:5000/파일이름 접근 시 이미지 파일 접근 가능
이렇게 안하면 접근 불가능하다
이미지 저장 필터 걸기
사진 파일만 올리기 위해서 fileFilter 추가
const upload = multer({
fileFilter: (req, file, cb) => {
//파일 확장자 제어
if (
["image/png", "image/jpeg", "image/jpg", "image/gif"].includes(
file.mimetype
)
) {
cb(null, true);
} else {
cb(new Error("invalid file type.", false));
}
},
});
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const { v4: uuid } = require("uuid"); //uuid 추가
const mime = require("mime-types"); //파일 확장자 제어
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) =>
cb(null, `${uuid()}.${mime.extension(file.mimetype)}`), //uuid 사용 + 파일 확장자 제어
});
const upload = multer({
storage,
fileFilter: (req, file, cb) => {
//파일 확장자 제어
if (
["image/png", "image/jpeg", "image/jpg", "image/gif"].includes(
file.mimetype
)
) {
cb(null, true);
} else {
cb(new Error("invalid file type.", false));
}
},
});
const app = express();
const PORT = 5000;
app.use("/uploads", express.static("uploads")); //uploads 폴더 외부 노출
//라우터 추가
app.post("/upload", upload.single("image"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
파일 사이즈 제한
const upload = multer({
//파일 사이즈 제한
limits: {
fileSize: 1024 * 1024 * 5,
},
});
//🏴☠️ server.js
const express = require("express");
const multer = require("multer"); //multer 미들웨어 추가
const { v4: uuid } = require("uuid"); //uuid 추가
const mime = require("mime-types"); //파일 확장자 제어
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, "./uploads"),
filename: (req, file, cb) =>
cb(null, `${uuid()}.${mime.extension(file.mimetype)}`), //uuid 사용 + 파일 확장자 제어
});
const upload = multer({
storage,
fileFilter: (req, file, cb) => {
//파일 확장자 제어
if (
["image/png", "image/jpeg", "image/jpg", "image/gif"].includes(
file.mimetype
)
) {
cb(null, true);
} else {
cb(new Error("invalid file type.", false));
}
},
//파일 사이즈 제한
limits: {
fileSize: 1024 * 1024 * 5,
},
});
const app = express();
const PORT = 5000;
app.use("/uploads", express.static("uploads")); //uploads 폴더 외부 노출
//라우터 추가
app.post("/upload", upload.single("image"), (req, res) => {
console.log(req.file);
res.json(req.file);
});
app.listen(PORT, () => console.log(`서버 ${PORT}번 살아있음~🚗`));
클라이언트
create-reat-app 설치
npx create-react-app client
기본적인 클라이언트 소스 코드
import React, { useState } from "react";
import axios from "axios";
const UploadForm = () => {
const [file, setFile] = useState(null);
const [fileName, setFileName] = useState("이미지 파일을 업로드 해주세요");
const handleImageSelect = (e) => {
const imageFile = e.target.files[0];
console.log({ imageFile });
setFile(imageFile);
setFileName(imageFile.name);
};
const onSubmit = async (e) => {
e.preventDefault();
console.log("제출");
const formData = new FormData();
formData.append("image", file); //서버의 upload.single("image") 이 부분이랑 key 맞춰줘야함
const res = await axios.post("/upload", formData, {
headers: { "Content-type": "multipart/form-data" },
});
console.log({ res });
alert("성공");
try {
} catch (err) {
alert("실페");
console.log(err);
}
};
return (
<form onSubmit={onSubmit}>
<label htmlFor="image">{fileName}</label>
<input id="image" type="file" onChange={handleImageSelect} />
<button type="submit">제출</button>
</form>
);
};
export default UploadForm;
'node.js' 카테고리의 다른 글
node.js next 함수를 이용한 Express 미들웨어 실행 (0) | 2024.01.04 |
---|---|
몽고db 기본 연결 (0) | 2023.09.19 |