저번시간에 AWS 셋팅 완료했으면
이제 글과 함께 이미지를 업로드할 수 있는 기능을 만들어봅시다.
1. 유저가 글과함께 이미지를 서버로 전송하면
2. 서버는 그걸 S3에 저장시켜주면 끝이겠죠
근데 저장하면 끝이아니라
나중에 그 이미지를 html페이지 이런데서 보여주고 싶으면 어떻게 하죠?
어떻게 하냐면 S3에 파일이나 이미지를 업로드하면
URL을 하나 알려주는데 그 URL로 접속하면 이미지가 나옵니다.
그래서 이미지 URL을 DB에 글과 함께 저장해뒀다가 필요할 때 꺼내쓰면 됩니다.
그래서 글과함께 이미지 업로드할 수 있는 기능을 쭉 한글로 정리부터 하면
1. 글작성페이지에 이미지 업로드할 수 있는 인풋하나 만들고
2. 글과 이미지를 서버로 전송시 서버는 전송된 이미지를 S3에 저장시키고
3. 그럼 URL을 하나 뱉어주는데 그걸 DB에 글과함께 저장
4. 나중에 이미지 필요할 때 DB에 있던 URL 꺼내쓰기
1. 글작성 페이지에 input 하나 만들기
write.ejs로 들어가봅시다.
<form class="form-box" action="/add" method="POST" enctype="multipart/form-data">
<input type="file" name="img1" accept="image/*">
(생략)
</form>
이미지나 파일을 서버로 전송하고 싶으면
- <form>태그엔 enctype을 저렇게 설정해주고
- <input>에 type="file"과 name 속성도 잘 달아주면 됩니다.
그리고 accept 속성으로 이미지파일만 선택할 수 있게 제한할 수 있는데 제한이 아니라 권장일 뿐이라
파일타입을 아예 제한하고 싶으면 서버에서 확장자 검사해보는게 좋습니다.
2. 서버는 전송된 이미지를 S3에 저장시킴
서버에서 multer나 formidable이라는 라이브러리를 쓰면
업로드한 파일같은걸 좀 쉽게 다룰 수 있기 때문에 multer 이거 설치해서 사용해보도록 합시다.
npm install multer multer-s3 @aws-sdk/client-s3
터미널 열어서 설치합시다.
multer가 기본 라이브러리고 뒤에 2개는 S3 이용을 위해 필요한 라이브러리들입니다.
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 : 'IAM에서 발급받은 액세스키',
secretAccessKey : 'IAM에서 발급받은 시크릿키'
}
})
const upload = multer({
storage: multerS3({
s3: s3,
bucket: '님들버킷이름',
key: function (요청, file, cb) {
cb(null, Date.now().toString()) //업로드시 파일명 변경가능
}
})
})
server.js 상단에 복붙해두면 라이브러리 셋팅 끝입니다.
이제 중간중간에 설정 잘 기입하면 되는데
- region : 부분은 S3 리전 설정하는 부분인데 서울로 s3 셋팅해놨으면 ap-northeast-2 기입합시다.
- AWS의 IAM 메뉴에서 키랑 시크릿키 발급받아온 것도 집어넣읍시다. 털리면 안되니까 .env 파일 쓰는게 어떨까요
- 버킷이름 설정하고
- 저장할 파일명도 맘대로 바꿀 수 있습니다.
파일명을 안겹치게하려면 랜덤문자를 해싱해서 집어넣던가 아니면 현재시간을 섞거나 그래도 됩니다.
원래 파일명은 요청.file 하면 나옵니다.
app.post('/add', upload.single('img1'), (요청, 응답) => {
console.log(요청.file)
(생략)
})
셋팅 잘 해놨으면 원하는 곳에서 upload.single() 라고 미들웨어를 추가해주면
이제 img1 이런 name속성을 가진 이미지가 들어올 때 마다 S3에 자동으로 업로드해줍니다.
그래서 글발행해주는 /add API 에다가 추가해봤습니다.
S3 업로드 기능 구현 끝
그리고 업로드후엔 URL이 하나 생성되는데 그건 요청.file 아니면 요청.files 안에 들어있기 때문에 그걸 맘대로 가져다가 쓰면 되겠습니다.
남이 하는 말 호구처럼 그대로 믿지 말고
업로드 진짜 되나 직접 테스트해보고 S3도 들어가봅시다.
(참고) 여러장의 이미지를 동시에 업로드 하고 싶으면
<input multiple> 이런거 폼에 넣어두면 여러개 이미지 선택이 가능하고
서버에선 upload.single() 대신 upload.array(‘input의 name속성 이름’, 3) 를 씁시다.
3이라는 숫자는 한 번에 업로드할 이미지 최대갯수설정인데 맘대로 바꿉시다.
3. 이미지 URL을 글과 함께 DB에 저장
왜 저장하냐구요?
그래야 나중에 글 보여줄 때 업로드한 이미지도 보여주고 그럴거 아닙니까
그래서 글 document에 이미지 URL도 함께 저장해보도록 합시다.
참고로 이미지가 많으면 document 안에 array자료 같은것도 집어넣을 수 있기 때문에 그렇게 저장해도 상관없습니다.
app.post('/add', upload.single('img1'), (요청, 응답) => {
console.log(요청.file)
await db.collection('post').insertOne({
title : 요청.body.title,
content : 요청.body.content,
img : 요청.file.location
})
(생략)
})
DB에 글발행할 때 img : 항목도 집어넣으라고 했습니다.
요청.file 안에 있던 이미지 URL을 넣어봤습니다.
참고로 <img src=" "> 안에 이미지 URL을 집어넣으면 이미지를 html 파일안에서 보여줄 수 있습니다.
에러처리 하고싶으면
S3가 이상하거나 그러면 에러가 날 수 있습니다.
이상한 에러가 나면 서버도 멈출 수 있기 때문에 그러기 싫으면
에러상황 처리하는 코드도 잘 작성해둡시다.
app.post('/add', (요청, 응답) => {
upload.single('img1')(요청, 응답, (err)=>{
if (err) return 응답.send('에러남')
이미지 업로드성공시 실행할 코드~~
})
})
upload.single()을 여기 작성하면 에러처리도 가능해서 이렇게 쓰는게 나을 수 있습니다.
이미지 업로드 성공시 글발행하라고 코드 수정하면 될듯요
오늘의 숙제 :
글마다 상세페이지 방문시
이미지가 있다면 이미지도 상세페이지 어딘가에 보여주도록 합시다.
이미지는 그냥 html 파일에 <img src="이미지URL"> 집어넣으면 보입니다.
쉬워서 답은 없음
'Node.js' 카테고리의 다른 글
node>AWS에 Node.js 서버 배포하기 (Elastic Beanstalk) (0) | 2024.09.19 |
---|---|
node>API들 다른 파일로 분리하기 (Router) (4) | 2024.09.19 |
node> 이미지 업로드 기능 만들기 (AWS S3 셋팅) (0) | 2024.07.27 |
node>환경변수 / 미들웨어 (0) | 2024.07.26 |
node> 회원기능 만들기 (passport, 로그인기능,세션,가입기능, connect-mongo) (0) | 2024.07.26 |