28. uploadPhoto in S3(2)

김종민·2022년 4월 26일
0

insta-backend

목록 보기
28/37

1. use Altair

2. shared/shared.utils.js

import AWS from 'aws-sdk'

AWS.config.update({
  credentials: {
    accessKeyId: process.env.AWS_KEY,
    secretAccessKey: process.env.AWS_SECRET,
  },
})
///기본 설정!! .env안에 AWS_KEY와 AWS_SECRET를 저장해 놓았음.

export const uploadToS3 = async (file, userId, folderName) => {
    console.log(file)
    ///uploadToS3라는 component를 만들어서 uploadPhoto와 editProfile에서사용
    /// ex)editProfile.resolver.js
    ////===> avatarUrl = await uploadToS3(avatar, loggedInUser.id, "avatars")
    ///ex)uploadPhoto.resolver.js
    ///const fileUrl = await uploadToS3(file, loggedInUser.id, "uploads")
    ///file: fileUrl
    ///반드시 console.log(file)을 찍어서 filename과 createReadStream 위치 확인할것
    
  const {
    filename, createReadStream 
  } = await file
  ///editProfile(avatar), uploadPhoto(file)로 부터 밭은 file에서 
  ///filename과 createReadStream 위치 확인.
  
  const readStream = createReadStream()
  const objectName = `${folderName}/${userId}-${Date.now()}-${filename}`
  ///S3에 들어갈 filename을 만듬, filder도 지정해 줄 수 있음.
  
  const { Location } = await new AWS.S3()
    .upload({
      Bucket: 'schoolgram',
      ///aws에서 만들었던 bucket의 name
      
      Key: objectName,
      ///저장될 filename
      
      ACL: 'public-read-write',
      Body: readStream,
    })
    .promise()
  console.log(Location)
  return Location
  ///S3, bucket에 저장된 후 url을 return함.
  ///url은 Location에 저장되어 return됨.
  /// uploadPhoto, editProfile에서 return 된 Location(url) 즉, url을 returl받음.
  
}

3. editProfile.resolver.js

import bcrypt from 'bcryptjs'
import prisma from '../../client'
import { protectedResolver } from '../users.util'
import fs from 'fs'
import { uploadToS3 } from '../../shared/shared.utils'

const resolveFn = async (
  _,
  { username, email, password: newPassword, bio, avatar },
  { loggedInUser }
) => {
  let avatarUrl = null
  if (avatar) {
    avatarUrl = await uploadToS3(avatar, loggedInUser.id, "avatars")
    ///avatar는 image File임, avatar, loggedInUser.id, 'avatars'(folder  이름)
    ///위 3개를 args로 shared.utils.js의 uploadToS3 component에 보냄.
    ///그리고 return으로 S3에 저장된 url을 return받아 avatarUrl에 저장함.
    
    
    --------->server에 photo저장하기 위해서 밑의 code 참조.
    // const {
    //   file: { filename, createReadStream },
    // } = await avatar
    // const newFilename = `${loggedInUser.id}-${Date.now()}-${filename}`
    // const readStream = createReadStream()
    // const writeStream = fs.createWriteStream(
    //   process.cwd() + '/uploads/' + newFilename
    // )
    // readStream.pipe(writeStream)
    // avatarUrl = `http://localhost:4000/static/${newFilename}`
  }

  let uglyPassword = null
  if (newPassword) {
    uglyPassword = await bcrypt.hash(newPassword, 10)
  }
  console.log(loggedInUser)
  const updatesUser = await prisma.user.update({
    where: {
      id: loggedInUser.id,
    },
    data: {
      username,
      email,
      bio,
      ...(uglyPassword && { password: uglyPassword }),
      ...(avatarUrl && { avatar: avatarUrl }),
    },
  })
  if (updatesUser.id) {
    return {
      ok: true,
    }
  } else {
    return {
      ok: false,
      error: 'Could not update profile',
    }
  }
}

export default {
  Mutation: {
    editProfile: protectedResolver(resolveFn),
  },
}

4. uploadPhoto.resolver.js

import prisma from '../../client'
import { uploadToS3 } from '../../shared/shared.utils'
import { protectedResolver } from '../../users/users.util'

export default {
  Mutation: {
    uploadPhoto: protectedResolver(
      async (_, { file, caption }, { loggedInUser }) => {
        let hashtagObj = []
        if (caption) {
          const hashtags = caption.match(/#[\w]+/g)
          hashtagObj = hashtags.map((hashtag) => ({
            where: { hashtag },
            create: { hashtag },
          }))
        }
        const fileUrl = await uploadToS3(file, loggedInUser.id, "uploads")
        ///shared/sahred.utils.js의 uploadToS3에 3개의 args를 보내서
        ///upload할 photo의 file을 S3의 bucket에 저장한 후 url을 return받음(fileUrl에)
        
        return prisma.photo.create({
          data: {
            file: fileUrl,
            caption,
            user: {
              connect: {
                id: loggedInUser.id,
              },
            },
            ...(hashtagObj.length > 0 && {
              hashtags: {
                connectOrCreate: hashtagObj,
              },
            }),
          },
        })
      }
    ),
  },
}

5. Upload Type이 문제를 일으킬 수 있음.

밑의type들을 참고해서 upload type이 문제를 일으킬 경우 참고바람.

  1. shared/shared. resolvers.js
import { GraphQLUpload } from 'graphql-upload'

export default {
  Upload: GraphQLUpload,
}
  1. editProfile.typeDefs.js
import { gql } from 'apollo-server'
import { GraphQLUpload } from 'graphql-upload'

export default gql`
  scalar Upload

  type EditProfileResult {
    ok: Boolean!
    error: String
  }
  type Mutation {
    editProfile(
      username: String
      email: String
      password: String
      bio: String
      avatar: Upload
    ): EditProfileResult!
  }
`
  1. uploadPhoto.typeDefs.js
import { gql } from 'apollo-server'
import { GraphQLUpload } from 'graphql-upload'

export default gql`
  scalar Upload

  type Mutation {
    uploadPhoto(file: Upload!, caption: String): Photo
  }
`
profile
코딩하는초딩쌤

0개의 댓글