SMALL
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[Node.js 교과서]의 책을 참고하여 포스팅한 개인 공부 내용입니다.
익스프레스로 SNS 서비스 만들기
multer 패키지로 이미지 업로드 구현하기
패키지 설치
$ yarn add multer
input 태그를 통해 이미지를 선택할 때 바로 업로드를 진행하고, 업로드된 사진 주소를 다시 클라이언트에 알릴 것입니다.
또한, 게시글을 저장할 때는 데이터베이스에 직접 이미지 데이터를 넣는 대신 이미지 경로만 저장하며 이미지는 서버 디스크에 저장됩니다.
routes/post.ts
import express from "express";
import multer from "multer";
import path from "path";
import fs from "fs";
import { isLoggedIn } from "../middlewares";
import { afterUploadImage, uploadPost } from "../controllers/post";
const router = express.Router();
try {
fs.readFileSync("uploads");
} catch (error) {
console.error("uploads 폴더가 없어 uploads 폴더를 생성합니다.");
fs.mkdirSync("uploads");
}
const upload = multer({
storage: multer.diskStorage({
destination(req, file, cb) {
cb(null, "uploads/");
},
filename(req, file, cb) {
const ext = path.extname(file.originalname);
cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
},
}),
limits: { fileSize: 5 * 1024 * 1024 },
});
// POST /post/img
router.post("/img", isLoggedIn, upload.single("img"), afterUploadImage);
// POST /post
const upload2 = multer();
router.post("/", isLoggedIn, upload.none(), uploadPost);
export default router;
controllers/post.ts
import Post from "../models/post";
import Hashtag from "../models/hashtag";
import { NextFunction, Request, Response } from "express";
const afterUploadImage = (req: Request, res: Response) => {
console.log(req.file);
res.json({ url: `/img/${req.file!.filename}` });
};
const uploadPost = async (req: Request, res: Response, next: NextFunction) => {
try {
const post = await Post.create({
content: req.body.content,
img: req.body.url,
UserId: req.user!.id,
});
const hashtags = req.body.content.match(/#[^\s#]*/g);
if (hashtags) {
const result = await Promise.all(
hashtags.map((tag: string) => {
return Hashtag.findOrCreate({
where: { title: tag.slice(1).toLowerCase() },
});
})
);
await post.addHashtags(result.map((r) => r[0]));
}
res.redirect("/");
} catch (error) {
console.error(error);
next(error);
}
};
export { afterUploadImage, uploadPost };
POST /post/img 라우터에서는 이미지 하나를 업로드 받은 뒤 이미지의 저장 경로를 클라이언트로 응답합니다.
static 미들웨어가 /img 경로의 정적 파일을 제공하므로 클라이언트에서 업로드한 이미지에 접근할 수 있습니다.
POST /post 라우터는 게시글 업로드를 처리하는 라우터입니다.
만일 이전 라우터에서 이미지를 업로드 했다면, 이미지 주소도 req.body.url로 전송됩니다. (이미지 주소가 넘어온 것이므로 none 메소드 사용)
게시글을 데이터베이스에 저장한 후 게시글 내용에서 해시태그를 정규표현식으로 추출해내었습니다.
추출할 해시태그는 #를 떼고 소문자로 변경한 후 저장하였으며, findOrCreate 메소드를 이용해 데이터베이스에 해시태그가 존재하면 가져오고, 존재하지 않으면 생성해주었습니다.
결괏값으로 [모델, 생성여부]를 리턴해주기 때문에, 모델만 추출하여 post.addHashtags 메소드로 게시글과 연결하였습니다.
controllers/page.ts
import { NextFunction, Request, Response } from "express";
import User from "../models/user";
import Post from "../models/post";
export const renderProfile = (req: Request, res: Response) => {
res.render("profile", { title: "내 정보 - NodeBird" });
};
export const renderJoin = (req: Request, res: Response) => {
res.render("join", { title: "회원 가입 - NodeBird" });
};
export const renderMain = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const post = await Post.findAll({
include: {
model: User,
attributes: ["id", "nick"],
},
order: [["createdAt", "DESC"]],
});
res.render("main", {
title: "NodeBird",
twits: post,
});
} catch (error) {
console.error(error);
next(error);
}
};
LIST
'JavaScript > Node.js' 카테고리의 다른 글
Node) RESTful API 정리 (0) | 2023.01.04 |
---|---|
Node) 시퀄라이즈 정리 (0) | 2023.01.03 |
Node) 익스프레스로 SNS 서비스 만들기 - Passport 모듈로 로그인 구현하기 (0) | 2023.01.02 |
Node) 익스프레스로 SNS 서비스 만들기 - 프로젝트 구조 갖추기, 모델 생성, 데이터베이스 연결 (0) | 2023.01.02 |
Node) sequelize 사용하기 - typescript, express, 쿼리 알아보기 (0) | 2022.12.30 |