image/video upload s3

김종민·2022년 11월 13일
0

Youtube

목록 보기
21/23

image와 video를 s3에 upload 해보자


1. bucket만들기

  1. aws에 가입하고 bucket을 만든다. 검색창에서 S3라고 입력한다.


2. 검색에서 S3를 검색해서 이 페이지에 왔으면, 버킷만들기를 클릭한다.

3. 버킷이름은 unique로 하고 리전은 서울을 선택한다.


4. 객체 소유권은 위와 같이 선택한다.


5. 모든퍼블릭 액세스 차단은 해제한다.


6. 맨 밑에 클릭 해준다.

  1. 버킷 만들기를 클릭한다.

2. user만들기


1. 검색에서 IAM을 클릭하면 위와 같은 페이지에 온다.


2. 사용자를 클릭하고, 사용자 추가를 클릭한다.


3. 사용자 이름을 입력하고, 액세스키는 프로그래밍방식으로 클릭한다.


4. 그룹에 사용자 추가를 하고, 정책은 AmazonS3FullAccess로 한다.
검색에서 S3를 입력하면, 정책이 나온다.

  1. 마지막으로 액세스키 ID와 비밀액세스키를 확인하고 나면,
    .env에 AWS_ID와 AWS_SECRET로 위의 두 값을 입력해 놓는다.

여기까지 하면, aws에서의 setting은 끝난다.

3. src/moddleware.js

npm i multer-s3
npm i aws-sdk

multer-s3와 aws를 설치한다.

import multer from 'multer'
import multerS3 from 'multer-s3'
import aws from 'aws-sdk'

const s3 = new aws.S3({
  credentials: {
    accessKeyId: process.env.AWS_ID,
    secretAccessKey: process.env.AWS_SECRET,
  },
})
///위와 같이 s3 instance를 만든다.
///AWS_ID와 AWS_SECRET를 .env에 저장해 놓은것을 불러준다.

const isHeroku = process.env.NODE_ENV === 'production'

const s3ImageUploader = multerS3({
  s3: s3,
  bucket: 'jmtube/images',
  acl: 'public-read',
})
///image를 s3에 upload하는 middleware
///bucket은 bucket name에 image폴더를 설정해준다.
///acl은 반드시 'public-read'로 한다.

const s3VideoUploader = multerS3({
  s3: s3,
  bucket: 'jmtube/videos',
  acl: 'public-read',
})
///video를 s3에 upload하는 middleware
///bucket은 bucket name에 videos폴더를 설정해준다.
///acl은 반드시 'public-read'로 한다.

export const localsMiddleware = (req, res, next) => {
  res.locals.loggedIn = Boolean(req.session.loggedIn)
  res.locals.loggedInUser = req.session.user || {}
  res.locals.siteName = 'jmTube'
  res.locals.isHeroku = isHeroku
  next()
}

export const protectorMiddleware = (req, res, next) => {
  if (req.session.loggedIn) {
    return next()
  } else {
    req.flash('error', 'Not authorized')
    return res.redirect('/login')
  }
}

export const publicOnlyMiddleware = (req, res, next) => {
  if (!req.session.loggedIn) {
    return next()
  } else {
    req.flash('error', 'Not authorized')
    return res.redirect('/')
  }
}

export const avatarUpload = multer({
  dest: 'uploads/avatars/',
  limits: {
    fileSize: 4000000,
  },
  storage: isHeroku ? s3ImageUploader : undefined,
})
///위에서 만든 s3ImageUploader, s3VideoUploader를
///위와 아래와 같이 storage에 넣어주면 끝난다.
///isHeroku인 경우는 S3에 upload하고, local인 경우는
///undefined로 설정하면, server에 upload한다.
///S3에서 fileUrl을 받는 부분은 아래의 pug파일을 확인한다.

export const videoUpload = multer({
  dest: 'uploads/videos/',
  limits: {
    fileSize: 250000000,
  },
  storage: isHeroku ? s3VideoUploader : undefined,
})

// export const recording = (req, res, next) => {
//   res.header('Cross-Origin-Embedder-Policy', 'require-corp')
//   res.header('Cross-Origin-Opener-Policy', 'same-origin')
//   next()
// }

4.src/controllers/videoController.js

import User from '../models/User'
import Video from '../models/Video'
import Comment from '../models/Comment'

export const getUpload = (req, res) => {
  return res.render('upload', { pageTitle: 'Upload Video' })
}
export const postUpload = async (req, res) => {
  const {
    user: { _id },
  } = req.session
  const file = req.file
  const { title, description, hashtags } = req.body
  const isHeroku = process.env.NODE_ENV === 'production'
  ///production mode인지 확인하는 것!
  
  try {
    const newVideo = await Video.create({
      owner: _id,
      title,
      fileUrl: isHeroku ? file.location : file.path,
      ///S3에서 video를 upload하면, video의 path는
      ///file.location으로 찍히니, production 모드인,
      ///isHeroku일때는 DB에 fileUrl을 넣을떄,
      ///file.location으로 찍어주어야 한다.
      ///server에 video를 upload(local)시에는
      ///file.path를 fileUrl에 담아주면 된다.
      ///image도 마찬가지
      
      description,
      hashtags: Video.formatHashtags(hashtags),
    })
    const user = await User.findById(_id)
    user.videos.push(newVideo._id)
    user.save()
    return res.redirect('/')
  } catch (error) {
    console.log(error)
    return res.status(404).render('upload', {
      pageTitle: 'Upload Video',
      errorMessage: error._message,
    })
  }

  // const dbVideo = await video.save()
  //console.log(dbVideo)
}

5.src/controllers/userController.js

export const postUserEdit = async (req, res) => {
  const {
    session: {
      user: { _id, avatarUrl, email: sessionEmail, username: sessionUsername },
    },
    body: { name, email, username, location },
    file,
  } = req
  console.log(file)

  let searchParam = []
  if (sessionEmail !== email) {
    searchParam.push({ email })
  }
  if (sessionUsername !== username) {
    searchParam.push({ username })
  }
  if (searchParam.length > 0) {
    const foundUser = await User.findOne({ $or: searchParam })
    if (foundUser && String(foundUser._id) !== String(_id)) {
      return res.status(400).render('edit-profile', {
        pageTitle: 'Edit Profile',
        errorMessage: 'This username/email is already taken',
      })
    }
  }
  const isHeroku = process.env.NODE_ENV === 'production'
  ///Heroku mode인지 확인시키는것!
  
  const updateUser = await User.findByIdAndUpdate(
    _id,
    {
      avatarUrl: file ? (isHeroku ? file.location : file.path) : avatarUrl,
      ///production mode일때는, s3에서 image를 upload하게
      ///s3에 upload하면, file.location으로 url을 받음.
      ///server(local)에 파일을 upload하면, file.path로 
      ///url을 받음.
      
      name,
      username,
      email,
      location,
    },
    { new: true }
  )
  // req.session.user = {
  //   ...req.session.user,
  //   name,
  //   email,
  //   username,
  //   location,
  // }
  req.session.user = updateUser
  return res.redirect('/')
}

!!!video파일을 너무 올리면, 과금이 될 우려가 있으니, 비디오 파일 upload는 조심하자!!!!
!!! 그리고 pug에서 s3파일을 load할떄 src='/'+avatarUrl 에서 '/'는
빠진다는 점을 유의하자!!!!

profile
코딩하는초딩쌤

1개의 댓글

comment-user-thumbnail
2023년 4월 26일

@snake games
좋아요. 파일을 업로드할 때 매우 주의하십시오. 부과될 가능성이 있기 때문에

답글 달기