nuxt3, aws s3 signedURL

마조리카·2023년 3월 30일
0

기존 프로젝트에서 aws s3에 이미지 업로드 방식을 aws lambda 방식을 사용하고 있었어요

큰 이미지를 업로드 하거나 영상을 업로드 할때 413 payload too large 에러가 발생 해서

다른 방식을 찾던중 s3 signed URL 방식을 찾게 되었습니다.

미리 승인된 URL에 이미지를 업로드하는 방식이라 용량제한이 없다는게 사용하기에 좋겠다고 생각하고 적용했습니다.

아래는 적용 예시입니다.

nuxt3 서버 쪽 코드
server/api/file/uploadjs.js

// AWS SDK 및 S3 클라이언트와 PutObjectCommand를 가져옴
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'


export default defineEventHandler(async event => {
// NUXT 런타임 환경 구성에서 AWS 액세스 키, 시크릿 액세스 키 및 REGION을 가져옴
const { AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION } = useRuntimeConfig()
// 내 S3 버킷을 지정한 S3 클라이언트 객체 생성
//AWS SDK에서 제공하는 S3 서비스를 이용하기 위해 사용하는 객체입니다. 이 객체를 생성하면, S3에 파일을 업로드하거나 다운로드, 삭제 등의 작업을 수행할 수 있습니다. S3 클라이언트 객체는 AWS 액세스 키, 시크릿 액세스 키, REGION 등의 인증 정보를 사용하여 AWS 서비스와 통신합니다. 이를 통해 S3 서비스와 상호 작용하는 API를 호출할 수 있습니다.
const s3 = new S3Client({
region: AWS_REGION,
credentials: {
accessKeyId: AWS_ACCESS_KEY_ID,
secretAccessKey: AWS_SECRET_ACCESS_KEY,
},
})

// 핸들러 이벤트에서 쿼리를 가져옴 
let query = getQuery(event)

// 현재 시간을 기반으로 고유한 파일 키 생성
const timestamp = new Date().getTime()
const key = ${timestamp}_${query.fileName}

// S3에 업로드될 파일의 속성을 정의하는 매개 변수 객체 생성
const params = {
Bucket: '내 버킷 이름',
Key: key,
ContentType: query.fileType,
}

// 업로드할 파일에 대한 PutObjectCommand 객체 생성
// PutObjectCommand를 사용하여 S3 버킷에 객체를 업로드할 수 있다
const command = new PutObjectCommand(params)

// 미리 서명 된 URL을 생성
const signedUrl = await getSignedUrl(s3, command, {
expiresIn: 3600, // URL 만료 시간 (초)
})

// 생성된 미리 서명 된 URL을 반환
return signedUrl
})





프론트쪽 코드
pages/fileUpload.vue


<script setup>
  const file = ref(null)
  const uploadUrl = ref(null)

  const handleFileUpload = async event => {
    const selectedFile = event.target.files[0]
    file.value = selectedFile

    const signedUrl = await $fetch('/api/file/upload', {
      method: 'get',
      query: {
        fileName: file.value.name,
        fileType: file.value.type,
      },
    })

    const response = await fetch(signedUrl, {
      method: 'PUT',
      body: file.value,
      headers: {
        'Content-Type': file.value.type,
      },
    })

    uploadUrl.value = response.url
    uploadUrl.value = new URL(uploadUrl.value)
  }
</script>

<template>
  <input type="file" @change="handleFileUpload" />
  <div>{{ uploadUrl?.origin + uploadUrl?.pathname }}</div>
</template>

<style scoped lang="scss"></style>

nuxt3 에서 s3 파일 업로드 방식을 고민하시는 분들은 참고하시기 바랍니다.

0개의 댓글