VaIice의 이야기

[Node.js] 이미지 보관 - AWS S3 (2) 본문

[Node.js]

[Node.js] 이미지 보관 - AWS S3 (2)

VaIice 2024. 7. 19. 18:32

 1. 이미지 업로드 과정 

 글 작성 페이지에 이미지 input 넣기 

 서버로 이미지 전송 

 이미지 URL 발급 

 DB에 게시글과 이미지 URL을 저장 

 DB에 있던 URL 꺼내서 삽입 

 

 

 2. 이미지 게시 

 
        <form class="form-box" action="/write" method="POST" enctype="multipart/form-data">
            <h4>글쓰기</h4>
            <input type="text" name="title">
            <input name="content">
            <input type="file" name="image" accept="image/*">
            <button type="submit">전송</button>
        </form>
 

 

 서버에서도 확장자 검사 필요 

 

 

 3. 관련 라이브러리 

 multer 

 formidable 

 ... 

 

 

 4. multer 사용법 

 npm install multer multer-s3 @aws-sdk/client-s3 

 

 multer: 유저가 보낸 파일 다루는 라이브러리 

 multer-s3: S3 업로드 라이브러리 

 @aws-sdk/client-s3: AWS 사용 라이브러리 

 

// server.js
 
const { S3Client } = require('@aws-sdk/client-s3')
const multer = require('multer')
const multerS3 = require('multer-s3')

const s3 = new S3Client({
  region : 'ap-northeast-2',
  credentials : {
      accessKeyId : process.env.ACCESS_KEY,
      secretAccessKey : process.env.SECRET_ACCESS_KEY
  }
})
const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: process.env.BUCKET_NAME,
    key: function (request, file, cb) {
      cb(null, Date.now().toString()) // 파일명
    },
    contentType: function (req, file, cb) {
      // 파일의 MIME 유형 설정
      cb(null, file.mimetype);
    }    
  })
})

 

 upload.single('input name') 실행하면 S3 업로드 

 contentType이 없다면, 확장자 대신 다운로드로 변환 

 

contentType 설정 전
contentType 설정 후

 

 

 
app.post('/write', upload.single('image'),async (request, response) => {
 

 

 name="image"인 이미지가 들어오면 S3 업로드 

 request.file로 출력 

 

 

 5. 이미지 여러 장 업로드 

 
     <form class="form-box" action="/write" method="POST" enctype="multipart/form-data" multiple>
 

 

 multiple 추가 

 

 
app.post('/write', upload.array('image', 2), async (request, response) => {  
 

 

 single -> array로 변경 

 개수 조절 가능 

 request.files로 출력 

 

 

 6. 예외 처리 

 
      // middleware X
   upload.single('image')(request, response, (err) => {
      if (err) return response.send('업로드 에러')
   })      
  try {
    if (!request.body.title) {
      response.send('제목을 입력해주세요.');
    } else if (!request.body.content) {
      response.send('내용을 입력해주세요.');
    }
    else {
      await db.collection('main').insertOne({
        title: request.body.title,
        content: request.body.content,
        image: request.file.location
      })
      let result = await db.collection('main').find().toArray()
      response.redirect('/')
    }
  }
 
 

 

 예외 처리를 할 때는, middelware X 

 try, catch 안에 upload문이 있다면, request, response 값 변경