upload.pug
input(type="file", accept="video/*", required, id="video", name="video")
middleware
export const avatarUpload = multer({
dest:"uploads/avatars/",
limits:{
fileSize: 3000000, --> byte
}})
export const videoUpload = multer({
dest:"uploads/videos/" ,
limits:{
fileSize: 10000000,
}})
videoRouter
videoRouter
.route("/upload")
.all(protectorMiddleware)
.get(getUpload)
.post(videoUpload.single("video"), postUpload);
videoController
export const postUpload = async (req, res) => {
const file = req.file; 또는 const {path:fileUrl} = req.file;이렇게 적어도됨 es6 req.file.path 이름을 fileUrl로 바꾸기
const { title, description, hashtags } = req.body;
try {
await Video.create({
title,
description,
fileUrl: file.path,
hashtags: Video.formatHashtags(hashtags),
});
Video.js 모델
const videoSchema = mongoose.Schema({
title: { type: String, required: true, uppercase: true, trim: true, minLength: 5 },
fileUrl:{ type:String, required: true },
pug
multer로 폼을 보내고싶으면 템플릿에 항상 적어줘야함
form(method ="POST", enctype="multipart/form-data" )
watch
video(src="/" + video.fileUrl, controls)
//////////////////////////
USER와 VIDEO연결하기
USER에는 여러개의 VIDEO 의 _id
VIDEO에는 소유자의(한 명) _id
Video 모델에 owner속성을 추가할 건데
type:ObjectId라고 하면 다른 String, Number처럼 노란색으로 나타나지 않음 (자바스크립트에서사용하는 타입의미)
owner:{type:mongoose.Schema.Types.ObjectId}로 작성
owner:{type:mongoose.Schema.Types.ObjectId, required:ture , ref:"User"} //object id 참고할 모델 이름
그리고 videoController에 postupload 수정
const {
user:{ _id }
} =req.session
try{
await Video.create{
owner: _id
}
}
--> 비디오 생성하고 db 열어보면 "owner": ObjectId("61c1cf35abbe2db93ce5981b"),로 속성이 추가됨
지금 이 상태는 쓰잘때기 없음 -->populate 사용
block content
video(src="/" + video.fileUrl, controls )
div
p=video.description
small=video.createdAt
small= video.owner
br
small= loggedInUser._id
if video.owner == loggedInUser._id // 두개의 형식이 각각 String, ObjectId여서 버튼이 보이지않음(적용이 되지않음)
a(href=`${video.id}/edit`) Edit video →
br
a(href=`${video.id}/delete`) Delete video →
그래서 if String(video.owner) == String(loggedInUser._id)처럼 string으로 감싸기
watch controller에서 console.log(video)
//
Video 모델이 오너의 아이디를 가지고있다.
{
meta: { views: 0, rating: 0 },
_id: new ObjectId("61c1cf51abbe2db93ce5981e"),
title: 'BUNNY',
fileUrl: 'uploads/videos/7b75cfd35cfe0503be7a671e973811bb',
description: 'bunny',
hashtags: [ '#bunny', '#bunny' ],
owner: new ObjectId("61c1cf35abbe2db93ce5981b"),
createdAt: 2021-12-21T12:57:53.135Z,
__v: 0
}
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
const owner = await User.findById(video.owner);
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found" });
}
return res.render("watch", { pageTitle: video.title, video, owner });
}
pug
block content
video(src="/" + video.fileUrl, controls )
div
p=video.description
small=video.createdAt
div
small= Uploaded by #{owner.name}
if String(video.owner) == String(loggedInUser._id)
a(href=`${video.id}/edit`) Edit video →
br
a(href=`${video.id}/delete`) Delete video →
postupload Controller에서
req.session의 id를 Video모델에 포함시켜 비디오 생성을 함
비디오에 영상소유자의 id를넣으면 좋은 점 1 소유자이름표시 2.소유자와 로그인된사용자 id비교해 표시하기
지금 db를 두번 요청하는 방식(Video, User))은 좀 안좋아보여서 popluate 속성을 이용해 다시 코딩해보겠음
-> 더 간단하게 populate : 실제데이터로 채워주는 역할
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id).populate("owner") //mongoose가 'video'찾고 그 안에서 "owner" 찾아서 실제 데이터로 넣어줌 model 만들 때 ref"User" User 모델 참고하라고 설정했음 const owner = await User.findById(video.owner);
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found" });
}
return res.render("watch", { pageTitle: video.title, video, owner });
}
small Uploaded by
a(href=`/users/${video.owner._id}`) #{owner.name video.owner.name} //owner변수 따로 안보내도 됨
if String(video.owner._id) == String(loggedInUser._id) //이제 video의 ower가 단순 문자가아니고 object객체라서 video.owner._id붙혀줘야함
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id).populate("owner")
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found" });
}
return res.render("watch", { pageTitle: video.title, video, owner });
user id 에 해당하는 영상들 찾아서 나타내기
export const see = async(req, res) => {
const {id} = req.params;
const user = await User.findById(id);
if(!user){
return res.status(404).render("404",{pageTitle: "User not found"});
}
const videos = await Video.find({owner: user._id}) // 여러개의영상이라 findById 아니고 find({})
//user._id는 오브젝트 형식이라
console.log(videos); 하면 배열로 나타남
return res.render("users/profile", {
pageTitle: `${user.name}의 Profile`,
user,
videos,
})
}
profile pug
extends ../base
include ../mixins/video
block content
each video in videos
+video(video)
else
li Sorry noth
위에 코드를 더 간단하게 만들기
유저는 여러가지 비디오를 가질 수있으니 videos라는 배열 속성을 만듦
const userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
avatarUrl:String,
socialOnly:{type:Boolean, default:false},
username: { type: String, required: true, unique: true },
password: { type: String, },
name: { type: String, required: true },
location: String,
videos:[{type: mongoose.Schema.Types.ObjectId , ref:"Video"}],
}); //Video model을 참고하여 objectId로
업로드 될 영상의 id를 USER 모델에서 저장해야함
export const postUpload = async (req, res) => {
const {
user: { _id },
} = req.session;
const {path:fileUrl} = req.file;
const { title, description, hashtags } = req.body;
try {
const newVideo = await Video.create({
title,
description,
fileUrl,
owner: _id,
hashtags: Video.formatHashtags(hashtags),
});
const user = await User.findById(_id);
user.videos.push(newVideo._id);
user.save();
see Controller
const user = await User.findById(id).populate("videos");
populate로 video의 id 배열이아닌 video의 object를 자체를 가져옴 console.log(user)로 확인가능
profile pug
block content
each video in user.videos
첫번 째 버그 비디오 업로드할 때마다 save();가 되는데
UserSchema에 저장하기 전 pre save 할 때 마다 비밀번호를 hashing 하라고 되어있기 때문
이는 사용자가 로그인을 못하게 되기 때문에 수정해야함
User.js
userSchema.pre("save", async function () {
if(this.isModified("password")){ 비밀번호가 변경 됐을 때만 //여기서 this는 User가르킴
this.password = await bcrypt.hash(this.password, 5);
}
});
두번째 버그
사용자일 때만 비디오 수정,삭제접근하기 getEdit, postEdit, deletevideo
export const postEdit = async (req, res) => {
const{
user:{_id},
} = req.session;
const { id } = req.params;
const { title, description, hashtags } = req.body;
const video = await Video.exist({ _id: id });
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found" })
}
if (String(video.owner) !== String(_id)){
return res.status(403).redirect("/"); //Stirng을 붙이지 않으면 값이 같더라도 타입이달라서 내가 영상 주인이라도 보이지않고 redirect 된다 , 타입은 typeof로 확인가능
}
await Video.findByIdAndUpdate(id, {
title,
description,
hashtags: Video.formatHashtags(hashtags),
})
return res.redirect(`/videos/${id}`);
}
deleteVideo 함수에서 User db에 남아있는 videos도 삭제
export const deleteVideo = async (req, res) => {
const { id } = req.params;
const {
user: { _id },
} = req.session;
const video = await Video.findById(id);
const user = await User.findById(_id);
if(!video){
return res.status(404).render("404", { pageTitle: "Video not found." });
}
if (String(video.owner) !== String(_id)) {
return res.status(403).redirect("/");
}
await Video.findByIdAndDelete(id);
user.videos.splice(user.videos.indexOf(id),1);
user.save();
return res.redirect("/");
}
'코딩 > Today I Learn' 카테고리의 다른 글
12.23공부 (0) | 2021.12.23 |
---|---|
12.22공부 프론트엔드 시작 (0) | 2021.12.22 |
12.16일 공부 (0) | 2021.12.16 |
12.15 공부 (0) | 2021.12.15 |
12.9 공부 (0) | 2021.12.14 |