Cloudinary
캠핑장을 생성할 때 이미지 파일을 입력받고 입력받은 이미지는 cloudinary라는 클라우드에 저장한다.
cloud name, api key, api secret을 사용할 예정이다.
패키지 설치
npm i multer dotenv cloudinary multer-storage-cloudinary
new 페이지의 form에 enctype="multipart/form-data"를 추가한다. multipart/form-data는 모든 문자를 인코딩하지 않음을 나명시한다. 파일이나 이미지를 서버로 전송할 때 사용한다. 서버에서 req.body를 출력해보면 body가 비어있는데, 이는 multipart/form-data를 파싱하지 않았기 때문이다. 파싱하기 위해 미들웨어 multer을 사용한다. cloudinary와 multer-storage-cloudinary 패키지는 cloudinary를 사용하기 위해 설치한다. 참고로 이미지 파일 여러개 입력받으려면 아래와 같이 input 타입이 file이고 multiple을 적어줘야 한다.
<input type="file" name="image" id="" multiple>
env
.env 파일을 생성하여 cloudinary를 사용하기 위한 키-값 쌍을 저장한다. Cloudinary의 Dashboard 내용을 적으면 된다.
CLOUDINARY_CLOUD_NAME=...
CLOUDINARY_KEY=...
CLOUDINARY_SECRET=...
.env 파일을 process.env로 로딩해주는 패키지를 설치하자.
npm i dotenv
app.js 최상단에 아래 코드를 추가하자. 코드는 개발 환경 또는 프로덕션 환경에서 실행된다. 개발 환경에서는 .env 파일에 정의한 변수를 가져와서 node 앱에 있는 process.env에 변수를 추가한다. 하지만 프로덕션 환경에서는 파일에 변수를 저장하지 않고 프로덕션 환경에 저장한다. 나중에 더 자세한 과정을 배우고 지금은 그냥 이렇게 하자.
if (process.env.NODE_ENV !== "production") {
require('dotenv').config();
}
Cloudinary 업로드
cloudinary 폴더를 새로 만들어 그 안에 index.js 파일을 생성하고 아래 코드를 입력한다.
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_KEY,
api_secret: process.env.CLOUDINARY_SECRET
});
const storage = new CloudinaryStorage({
cloudinary,
params: {
folder: 'YelpCamp',
allowedFormats: ['jpeg', 'jpg', 'png']
}
});
module.exports = {
cloudinary,
storage
}
routes의 campgound.js 에서 아래 코드처럼 upload.array를 미들웨어로 추가한다. 유효성 검사때문에 유효성 검사 미들웨어 앞에 적어놓긴했지만 동작하는데는 문제가 없는데 나중에 수정해야될 코드다. upload.array 안에 문자열은 html 페이지에서 사진을 입력받은 요소의 name과 일치해야 한다.
const multer = require('multer');
const { storage } = require('../cloudinary');
const upload = multer({ storage });
router.route('/')
.get(catchAsync(campgrounds.index))
.post(isLoggedIn, upload.array('image'), validateCampground, catchAsync(campgrounds.createCampground));
DB연결
여러 이미지를 입력할 수 있도록 배열로 변경하고, 이미지가 저장된 장소인 url, 이미지를 삭제할 때 필요한 filename 속성을 추가한다. campground 스키마가 정의되어 있는 파일에서 image 부분을 아래와 같이 수정한다.
images: [
{
url: String,
filename: String
}
]
캠핑장을 생성하는 코드에서 save 하기 전에 아래 코드를 추가한다. camp는 새로 생성한 캠핑장이다.
camp.images = req.files.map(f => ({ url: f.path, filename: f.filename }));
이미지 슬라이드로 표시
show.ejs 파일에서 이미지 표시하는 부분을 아래와 같이 수정한다.
<div id="carouselExample" class="carousel slide">
<div class="carousel-inner">
<% camp.images.forEach((image, i)=> { %>
<div class="carousel-item <%= i === 0 ? 'active' : '' %>">
<img src="<%= image.url %>" class="d-block w-100" alt="...">
</div>
<% }) %>
</div>
<% if(camp.images.length> 1) { %>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExample"
data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExample"
data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
<% } %>
</div>
'웹 프로그래밍' 카테고리의 다른 글
[YelpCamp 프로젝트] 지도 추가 (1) | 2023.12.08 |
---|---|
[Yelpcamp 프로젝트] 이미지 편집 (0) | 2023.12.07 |
[Yelpcamp 프로젝트] 로그인 구현 (0) | 2023.12.01 |
[JS] 로그인 상태 유지 (2) | 2023.12.01 |
[Yelpcamp 프로젝트] flash (0) | 2023.11.29 |