Skip to content

Commit

Permalink
Merge pull request #21 from 9oormthonUniv-seoultech/feat/#17
Browse files Browse the repository at this point in the history
feat: QR 및 갤러리에서 사진 업로드 / 삭제 기능 구현
  • Loading branch information
sooieese00 authored Nov 5, 2024
2 parents f84c04e + 58ee0d3 commit 2e6e158
Show file tree
Hide file tree
Showing 12 changed files with 748 additions and 3 deletions.
102 changes: 102 additions & 0 deletions controllers/photoController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const Photo = require('../models/photo');
const PhotoTemp = require('../models/photoTemp');
const User = require('../models/user');
const { deleteTemp } = require('../middlewares/uploadPhoto');
const { deleteImages } = require('../middlewares/s3');

const createTemp = async (req, res) => {
try{
console.log(req.body);
const { user_id, uploadedUrl } = req.body;
console.log(uploadedUrl);

const newTemp = await PhotoTemp.create({
user_id: user_id,
image_url: uploadedUrl
});

res.status(201).json( {status: 'success', newTemp});
} catch (err) {
console.error('이미지 업로드 중 오류: ', err);
res.status(500).json({ status: 'fail' , message: '이미지 업로드에 실패했습니다.'});
}
};

const updateInfo = async(req, res) => {
try {
const photoTemp_id = req.params.photoTemp_id;
const { date, photobooth_id } = req.body;

const temp = await PhotoTemp.findByPk(photoTemp_id);
temp.date = date;
temp.photobooth_id = photobooth_id;
await temp.save();
return res.status(200).json({status: 'success', message: '날짜 및 포토부스 장소 정보가 추가되었습니다.', temp});
} catch (err) {
console.error('업데이트 중 오류: ', err);
res.status(500).json({ status: 'fail' , message: '이미지 업로드에 실패했습니다.'});
}
};

const updateRecord = async (req, res) => {
try {
const photoTemp_id = req.params.photoTemp_id;
const { hashtag_1, hashtag_2, hashtag_3, record } = req.body;

const temp = await PhotoTemp.findByPk(photoTemp_id);
temp.hashtag_1 = hashtag_1;
temp.hashtag_2 = hashtag_2;
temp.hashtag_3 = hashtag_3;
temp.record = record;
await temp.save();
return res.status(200).json({status: 'success', message: '해시태그와 기록이 추가되었습니다.', temp});
} catch (err) {
console.error('업데이트 중 오류: ', err);
res.status(500).json({ status: 'fail' , message: '이미지 업로드에 실패했습니다.'});
}
};

const savePhoto = async (req, res) => {
try {
const photoTemp_id = req.params.photoTemp_id;
const temp = await PhotoTemp.findByPk(photoTemp_id);

const newPhoto = await Photo.create({
user_id: temp.user_id,
photobooth_id: temp.photobooth_id,
image_url: temp.image_url,
date: temp.date,
record: temp.record,
hashtag_1: temp.hashtag_1,
hashtag_2: temp.hashtag_2,
hashtag_3: temp.hashtag_3
});

if(!await deleteTemp(photoTemp_id)){
res.status(400).json({status: 'fail', message: 'Temp 삭제에 실패했습니다.'});
};

return res.status(201).json({status: 'success', message: '사진이 성공적으로 저장되었습니다!', newPhoto});
} catch (err) {
console.error('사진 저장 중 오류: ', err);
res.status(500).json({ status: 'fail' , message: '이미지 저장에 실패했습니다.'});
}
};

const deletePhoto = async (req, res) => {
try {
const photo_id = req.params.photo_id;
const photo = await Photo.findByPk(photo_id);

await deleteImages([photo.image_url]);
await photo.destroy();

return res.status(204).json({message: '이미지를 삭제했습니다.'});
} catch(err) {
console.error('사진 삭제 중 오류: ', err);
res.status(500).json({message: '이미지 삭제에 실패했습니다.'});
}
};


module.exports = { createTemp, updateInfo, updateRecord, savePhoto, deletePhoto };
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ app.use('/api/user', userRouter);
const mapRouter = require('./routes/mapRouters');
app.use('/api/map', mapRouter);

const photoRouter = require('./routes/photoRouter');
app.use('/api/photo', photoRouter);

// 스웨거 세팅
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
Expand Down
63 changes: 62 additions & 1 deletion middlewares/s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,68 @@ const saveUploadOneImage = async (req, res, next) => {
}
};

// URL로 이미지 하나 업로드하는 미들웨어 (반환값 없고, s3 url을 req.body에 담음)
const uploadOneImageUrl = async (req, res, next) => {
const imageUrl = req.body.imageUrl;
try {
const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });

mimeType = response.headers['content-type'];
console.log(mimeType);
let extension = '';
if (mimeType === 'image/jpeg') {
extension = '.jpg';
} else if (mimeType === 'image/png') {
extension = '.png';
} else if (mimeType === 'image/bmp') {
extension = '.bmp';
} else if (mimeType === 'application/octet-stream') {
mimeType = 'image/png';
extension = '.png';
} else {
throw new Error('허용된 파일 형식이 아닙니다');
}

const fileName = `${uuid()}${extension}`;
const params = {
Bucket: process.env.S3_BUCKET_NAME,
Key: fileName,
Body: response.data,
ContentType: mimeType,
};
await s3.putObject(params).promise();

const uploadedUrl = `https://${params.Bucket}.s3.ap-northeast-2.amazonaws.com/${params.Key}`;
req.body.uploadedUrl = uploadedUrl;
return next();
} catch (error) {
console.error('이미지 업로드 중 에러 발생:', error);
return res.status(500).json({ message: '이미지 업로드 중 에러 발생', error: error.message });
}
};

// 갤러리에서 이미지 하나 업로드하는 미들웨어 (사진 하나만 가능)
const uploadOneImage = (req, res, next) => {
multer({
storage,
limits: { fileSize: 5 * 1024 * 1024 }, // 파일 크기 제한
}).single('file')(req, res, (err) => { // 파일 크기,개수 제한
if (err) {
return res.status(400).json({ error: err.message });
}

console.log(req.file);
//S3에서 반환된 URL들을 저장하여 반환
if (req.file) {
const imageUrl = req.file.location;
console.log(imageUrl)
req.body.uploadedUrl = imageUrl; // 이미지 URL을 req.body에 저장
} else {
req.body.uploadedUrl = null;
}
next();
});
};

const deleteImages = async (imageUrls) => {
try {
Expand Down Expand Up @@ -116,4 +177,4 @@ const deleteImages = async (imageUrls) => {
}
};

module.exports = {uploadFiveImages, saveUploadOneImage, deleteImages}
module.exports = {uploadFiveImages, saveUploadOneImage, uploadOneImageUrl, uploadOneImage, deleteImages};
97 changes: 97 additions & 0 deletions middlewares/uploadPhoto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const axios = require('axios');
const cheerio = require('cheerio');
const PhotoTemp = require('../models/photoTemp');
const { deleteImages } = require('../middlewares/s3');

const photoismQR = async (uid) => {
try {
url = 'https://cmsapi.seobuk.kr/v1/etc/seq/resource';
const jsonData = { uid: uid };
console.log(uid);

const response = await axios.post(url, jsonData);
const data = response.data;

if (data.code === 1003) {
return 'expired';
}

const imagePath = data.content.fileInfo.picFile.path;
console.log("Image Path: ", imagePath);

return imagePath;
} catch (err) {
console.error('Error:', err);
}
};

const harufilmQR = async (url) => {
try {
const basePath = 'http://haru8.mx2.co.kr';

const response = await axios.get(url);
const html = response.data;

const $ = cheerio.load(html);
const imgPath = $('.main_cont img').attr('src');
const imagePath = basePath + imgPath;
console.log("Image Path: ", imagePath);

return imagePath;
} catch (err) {
console.error('Error:', err);
res.status(500).send('Failed to download an upload image');
}
};


const uploadImageByQR = async(req, res, next) => {
console.log(req.body);
const qr_url = req.query.url;
console.log(qr_url);

try {
const parsedUrl = new URL(qr_url);
const domain = parsedUrl.hostname;

let file;
if (domain === 'haru8.mx2.co.kr') {
imageUrl = await harufilmQR(qr_url);
// 하루필름
} else if (domain === 'qr.seobuk.kr') {
const uid = parsedUrl.searchParams.get('u');
if (uid === null)
res.status(400).json({status: 'fail', message: '이미 만료된 QR입니다.'});
imageUrl = await photoismQR(uid);
// 포토이즘
} else {
res.status(400).send('지원되지 않는 도메인입니다.');
return;
}

console.log(file);

if (file === 'expired')
res.status(400).json({status: 'fail', message: '이미 만료된 QR 입니다.'});

req.body.imageUrl = imageUrl;
next();
}
catch (err) {
console.error('Error:', err);
res.status(500).send('Failed to download an upload image');
}
};

const deleteTemp = async (photoTemp_id) => {
try {
const temp = await PhotoTemp.findByPk(photoTemp_id);
await temp.destroy();
return true;
} catch (error) {
console.error(error);
return false;
}
};

module.exports = { uploadImageByQR, deleteTemp };
10 changes: 10 additions & 0 deletions models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const Sequelize = require('sequelize');
const User = require('./user');
const Photobooth = require('./photobooth');
const Review = require('./review');
const Photo = require('./photo');
const PhotoTemp = require('./photoTemp');

const env = process.env.NODE_ENV || 'development';
const config = require('../configs/config')[env];
Expand All @@ -24,9 +26,17 @@ Photobooth.init(sequelize);
db.Review = Review;
Review.init(sequelize);

db.Photo = Photo;
Photo.init(sequelize);

db.PhotoTemp = PhotoTemp;
PhotoTemp.init(sequelize);

// 관계 설정
User.associate(db);
Photobooth.associate(db);
Review.associate(db);
Photo.associate(db);
PhotoTemp.associate(db);

module.exports = db;
Loading

0 comments on commit 2e6e158

Please sign in to comment.