Commit 1bc1c778 authored by Lee Soobeom's avatar Lee Soobeom
Browse files

fileinfo db save

parent 39e4b1fd
......@@ -2,8 +2,8 @@ import axios from "axios";
import baseUrl from "./baseUrl";
import { PostType } from "../types";
export const posting = async (post: PostType) => {
const { data } = await axios.post(`${baseUrl}/posts/`, post);
export const createImgAndPost = async (formdata: FormData) => {
const { data } = await axios.post(`${baseUrl}/posts/`, formdata);
return data;
};
......@@ -12,6 +12,11 @@ export const getData = async () => {
return data;
};
export const getImgData = async (name: string) => {
const { data } = await axios.get(`/images/${name}`);
return data;
};
export const addCounts = async (_id: string, counts: number) => {
const { data } = await axios.post(`${baseUrl}/posts/${_id}`, {
counts: counts + 1,
......@@ -33,8 +38,3 @@ export const updating = async (post: PostType) => {
const { data } = await axios.put(`${baseUrl}/posts/${post._id}`, post);
return data;
};
export const postImg = async (formdata: FormData) => {
const { data } = await axios.post(`${baseUrl}/posts`, formdata);
return data;
};
......@@ -8,8 +8,8 @@ import { postApi } from "../apis";
import { PostState } from "./intopost";
export function EditPost() {
const [city, setCity] = useState<string>("질문종류");
const [theme, setTheme] = useState<string>("질문종류");
const [city, setCity] = useState<string>("city");
const [theme, setTheme] = useState<string>("theme");
const [title, setTitle] = useState<string>("");
const [text, setText] = useState<string>("");
const navigate = useNavigate();
......@@ -65,10 +65,10 @@ export function EditPost() {
setError("내용을 입력해 주세요.");
return false;
} else if (equals(city, "city")) {
setError("테마를 선택해 주세요.");
setError("도시를 선택해 주세요.");
return false;
} else if (equals(theme, "theme")) {
setError("도시를 선택해 주세요.");
setError("테마를 선택해 주세요.");
return false;
} else {
return true;
......
......@@ -59,6 +59,7 @@ export function IntoPost() {
</div>
</div>
</div>
<div className="border-2 border-sky-300 rounded h-48">files</div>
<div className="border-2 border-sky-300 rounded h-96">{post.text}</div>
</div>
</div>
......
......@@ -12,7 +12,7 @@ export default function Posting() {
const [theme, setTheme] = useState<string>("theme");
const [title, setTitle] = useState<string>("");
const [text, setText] = useState<string>("");
const [file, setFile] = useState<File>();
const [file, setFile] = useState<FileList>();
const [imgSrc, setImgSrc] = useState<string[]>();
const navigate = useNavigate();
......@@ -32,35 +32,39 @@ export default function Posting() {
const [disabled, setDisabled] = useState(false);
const [success, setSuccess] = useState(false);
useEffect(() => {
console.log("uploaded imgs", imgSrc);
}, [imgSrc]);
const imgArr = new Array();
const sendImg2Db = async (filelist: FileList) => {
const formdata = new FormData();
formdata.append("title", user.title);
formdata.append("text", user.text);
formdata.append("theme", user.theme);
formdata.append("city", user.city);
if (!(filelist === undefined || filelist === null)) {
for (var i = 0; i < filelist.length; i++) {
formdata.append(`picture${i}`, filelist?.[i]);
formdata.append("picture", filelist?.[i]);
}
console.log("formdata", formdata);
await postApi.postImg(formdata);
// formdata: post, imgs
const res = await postApi.createImgAndPost(formdata);
}
// else {
// const res = await postApi.createImgAndPostTable(formdata);
// }
};
async function handlePostSubmit(event: FormEvent) {
event.preventDefault();
try {
setError("");
console.log("user data", user);
if (postingFormMatch()) {
if (postingFormMatch(user)) {
setLoading(true);
// sendImg2Db();
const res = await postApi.posting(user);
console.log("서버연결됬나요", res);
// console.log("user save");
if (file) {
sendImg2Db(file);
}
// const res = await postApi.posting(user);
// console.log("서버연결됬나요", res);
navigate("/board", { replace: true });
setSuccess(true);
setError("");
......@@ -73,19 +77,19 @@ export default function Posting() {
}
}
function postingFormMatch() {
function postingFormMatch(user: PostType) {
if (!isLength(user.title ?? "", { min: 1 })) {
setError("제목을 입력해 주세요.");
return false;
} else if (!isLength(user.text ?? "", { min: 1 })) {
setError("내용을 입력해 주세요.");
return false;
} else if (equals(city, "질문종류")) {
setError("테마를 선택해 주세요.");
return false;
} else if (equals(theme, "질문종류")) {
} else if (equals(city, "city")) {
setError("도시를 선택해 주세요.");
return false;
} else if (equals(theme, "theme")) {
setError("테마를 선택해 주세요.");
return false;
} else {
return true;
}
......@@ -124,10 +128,13 @@ export default function Posting() {
};
const handleInputPic = async (event: React.ChangeEvent<HTMLInputElement>) => {
event.preventDefault();
const maxImg = 10;
const { files } = event.target;
if (!(files === null)) {
setFile(files);
}
if (!(files?.length === undefined)) {
if (files?.length <= maxImg) {
for (var i = 0; i < files.length; i++) {
......@@ -140,7 +147,7 @@ export default function Posting() {
};
}
} else {
alert("사진은 최대 10장까지 업로드 가능합니다!");
alert(`사진은 최대 ${maxImg}장까지 업로드 가능합니다!`);
}
}
};
......
......@@ -16,7 +16,7 @@ export interface PostType {
text: string;
theme: string;
city: string;
date: string | number;
date: string;
counts: number;
_id: string;
user: string;
......
import formidable from "formidable";
import { asyncWrap } from "../helpers/asyncWrap";
import { TypedRequest } from "../types";
export const uploadFile = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequest;
const form = formidable({ multiples: false, uploadDir: "uploads" });
await new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
console.log("fields", fields);
console.log("files", files);
req.body = fields;
req.files = files;
resolve(files);
});
});
next();
return;
});
export const uploadFiles = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequest;
const form = formidable({ multiples: true, uploadDir: "uploads" });
await new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
console.log("fields", fields);
console.log("files", files);
req.body = fields;
req.files = files;
resolve(files);
});
});
next();
return;
});
export * as authCtrl from "./auth.controller";
export * as fileInfoCtrl from "./fileinfo.controller";
export * as mainimgCtrl from "./mainimg.controller";
export * as postCtrl from "./post.controller";
export * as roleCtrl from "./role.controller";
export * as userCtrl from "./user.controller";
export * as mainimgCtrl from "./mainimg.controller";
\ No newline at end of file
import { NextFunction, Request, Response } from "express";
import isLength from "validator/lib/isLength";
import equals from "validator/lib/equals";
import formidable, { Fields, Files } from "formidable";
import { TypedRequestAuth } from "./auth.controller";
import { asyncWrap } from "../helpers";
import { postDb, userDb } from "../db";
import { TypedRequest } from "../types";
export const postCreate = asyncWrap(async (reqExp, res, next) => {
export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
// const { date, counts } = req.body as {
// date: "";
// counts: 0;
// };
const { title, text, theme, city, date } = req.body as {
title: string;
text: string;
theme: string;
city: string;
date: Date;
counts: number;
};
const { userId } = req.auth;
// 1) title 빈 문자열인지 확인
if (!isLength(title ?? "", { min: 1 })) {
return res.status(422).send("제목을 한 글자 이상 입력해주세요");
}
const form = formidable({
uploadDir: "uploads",
keepExtensions: true,
multiples: true,
});
// 2) body 빈 문자열인지 확인
if (!isLength(text ?? "", { min: 1 })) {
return res.status(422).send("제목을 한 글자 이상 입력해주세요");
const fileIdArr = new Array();
form.parse(req, (err, fields, files) => {
const title = fields.title?.[0];
const text = fields.text?.[0];
const theme = fields.theme?.[0];
const city = fields.city?.[0];
if (Array.isArray(files.picture)) {
for (var i = 0; i < files.picture.length; i++) {
if (!(files.picture?.[i].originalFilename === null)) {
const originalfilename = files.picture?.[i].originalFilename;
const newfilename = files.picture?.[i].newFilename;
const filepath = files.picture?.[i].filepath;
const filesRes = postDb.createFilesRow(
originalfilename,
newfilename,
filepath
);
}
// 3) theme dropdown default-value "테마"일 경우 에러
if (equals(theme, "질문종류")) {
return res.status(422).send("테마를 입력해 주세요");
}
// 4) city dropdown default-value "도시"일 경우 에러
if (equals(city, "질문종류")) {
return res.status(422).send("도시를 선택해 주세요");
} else {
console.log("업로드한 사진이 없습니다.");
}
const userId = req.auth.userId;
const newPost = await postDb.createPost({
const postRes = postDb.createPostRow({
title,
text,
theme,
city,
date: Date.now(),
counts: 0,
user: userId,
});
console.log("post", newPost);
return res.json(newPost);
console.log("createPostRow", postRes);
});
});
export const getAllPost = asyncWrap(async (req, res) => {
const posts = await postDb.getPosts();
// console.log(posts);
console.log(posts);
return res.json(posts);
});
......
import { Post, PostType } from "../models";
import { FileInfo, IFileInfo } from "../models";
export const createPost = async (post: PostType) => {
const newPosting = await Post.create({
export const createPostRow = async (post: PostType) => {
const newPostRow = await Post.create({
title: post.title,
text: post.text,
theme: post.theme,
......@@ -10,7 +11,26 @@ export const createPost = async (post: PostType) => {
date: post.date,
counts: 0,
});
return newPosting;
console.log("check", newPostRow);
return newPostRow;
};
export const createFilesRow = async (
originalfilename?: string | null,
newfilename?: string,
picturepath?: string
) => {
const newFileRow = await FileInfo.create({
originalfilename: originalfilename,
newfilename: newfilename,
picturepath: picturepath,
});
return newFileRow;
};
export const findFileByPostInfo = async (title: string, usreId: string) => {
const posts = await Post.find({ title: title, userId: usreId });
return posts;
};
export const getPosts = async () => {
......
import bcrypt from "bcryptjs";
import { ObjectId } from "mongoose";
import { IUser, Role, Post, User, Avatar } from "../models";
import fs from "fs";
import { IUser, Role, Post, User, FileInfo } from "../models";
import fs from "fs/promises";
export const createUser = async (user: IUser) => {
// 비밀번호 암호화
const hash = await bcrypt.hash(user.password, 10);
const newAvatar = await Avatar.create({});
const newAvatar = await FileInfo.create({});
// 사용자 역할 추가: 기본값은 "user"
let userRole = null;
if (user.role) {
......@@ -82,17 +82,17 @@ export const postPicture = async (
if (!(profile?.avatar === undefined)) {
if (originalfilename === null) {
await Avatar.findByIdAndUpdate(profile.avatar._id, {
await FileInfo.findByIdAndUpdate(profile.avatar._id, {
nickname: nickname,
});
} else if (nickname === "") {
await Avatar.findByIdAndUpdate(profile.avatar._id, {
await FileInfo.findByIdAndUpdate(profile.avatar._id, {
originalfilename: originalfilename,
newfilename: newfilename,
picturepath: picturepath,
});
} else {
await Avatar.findByIdAndUpdate(profile.avatar._id, {
await FileInfo.findByIdAndUpdate(profile.avatar._id, {
originalfilename: originalfilename,
newfilename: newfilename,
picturepath: picturepath,
......@@ -102,14 +102,12 @@ export const postPicture = async (
}
};
export const deleteUser = async (userId: ObjectId) => {
export const deleteUser = async (userId: string) => {
const user = await User.findById(userId);
if (!(user?.avatar === undefined)) {
const ref = await Avatar.findById(user.avatar._id);
fs.unlink("../travel/uploads/" + ref?.newfilename, (err) => {
console.log(err);
});
await Avatar.deleteOne({ _id: user.avatar._id });
await User.deleteOne({ _id: userId });
if (user && user.avatar) {
const file = await FileInfo.findById(user.avatar._id);
await fs.unlink("../travel/uploads/" + file?.newfilename);
await FileInfo.deleteOne({ _id: user.avatar._id });
return await user.deleteOne();
}
};
import { model, Schema } from "mongoose";
export interface IAvatar {
export interface IFileInfo {
originalfilename?: string;
newfilename?: string;
picturepath?: string;
nickname?: string;
}
const Avatarschema = new Schema<IAvatar>({
originalfilename: { type: String, unique: true },
const schema = new Schema<IFileInfo>({
originalfilename: { type: String },
newfilename: { type: String },
nickname: { type: String },
picturepath: { type: String },
});
export default model<IAvatar>("Avatar", Avatarschema);
export default model<IFileInfo>("FileInfo", schema);
export { default as User, IUser } from "./user.model";
export { default as Post, PostType } from "./post.model";
export { default as Role } from "./role.model";
export { default as Avatar, IAvatar } from "./fileinfo.model";
export { default as FileInfo, IFileInfo } from "./fileinfo.model";
export { default as Mainimg, MainimgType } from "./mainimg.model";
......@@ -5,9 +5,10 @@ export interface PostType {
text: string;
theme: string;
city: string;
user: Types.ObjectId | string;
date: Date | number;
counts?: number;
user: Types.ObjectId | string;
file?: Types.ObjectId | string;
}
const PostSchema = new Schema<PostType>({
......@@ -37,6 +38,10 @@ const PostSchema = new Schema<PostType>({
type: Number,
default: 0,
},
file: {
type: Schema.Types.ObjectId,
ref: "FileInfo",
},
});
export default model<PostType>("Post", PostSchema);
......@@ -12,6 +12,5 @@ router.use("/auth", authRouter);
router.use("/posts", postRouter);
router.use("/profile", profileRouter);
router.use("/mainimg", mainimgRouter);
//posting함수 -> mongodb에 posts json형식으로 저장
export default router;
import express from "express";
import { postCtrl, authCtrl } from "../controllers";
import { postCtrl, authCtrl, fileInfoCtrl } from "../controllers";
const router = express.Router();
router.route("/").post(authCtrl.requireLogin, postCtrl.postCreate);
router.route("/").post(authCtrl.requireLogin, postCtrl.createImgAndPost);
router.route("/").get(postCtrl.getAllPost);
router
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment