feat: enhance image upload validation and management in CoffeeController
This commit is contained in:
parent
8aebdbb607
commit
1fce1f1831
@ -36,6 +36,14 @@ exports.create = async (req, res) => {
|
|||||||
let original_filename = null;
|
let original_filename = null;
|
||||||
let uploadedKey = null;
|
let uploadedKey = null;
|
||||||
if (req.file) {
|
if (req.file) {
|
||||||
|
const allowedMime = ['image/jpeg','image/png','image/webp'];
|
||||||
|
if (!allowedMime.includes(req.file.mimetype)) {
|
||||||
|
return res.status(400).json({ error: 'Invalid image type. Allowed: JPG, PNG, WebP' });
|
||||||
|
}
|
||||||
|
const maxBytes = 10 * 1024 * 1024; // 10MB
|
||||||
|
if (req.file.size > maxBytes) {
|
||||||
|
return res.status(400).json({ error: 'Image exceeds 10MB limit' });
|
||||||
|
}
|
||||||
const s3 = new S3Client({
|
const s3 = new S3Client({
|
||||||
region: process.env.EXOSCALE_REGION,
|
region: process.env.EXOSCALE_REGION,
|
||||||
endpoint: process.env.EXOSCALE_ENDPOINT,
|
endpoint: process.env.EXOSCALE_ENDPOINT,
|
||||||
@ -50,6 +58,7 @@ exports.create = async (req, res) => {
|
|||||||
Key: key,
|
Key: key,
|
||||||
Body: req.file.buffer,
|
Body: req.file.buffer,
|
||||||
ContentType: req.file.mimetype,
|
ContentType: req.file.mimetype,
|
||||||
|
ACL: 'public-read'
|
||||||
}));
|
}));
|
||||||
object_storage_id = key;
|
object_storage_id = key;
|
||||||
original_filename = req.file.originalname;
|
original_filename = req.file.originalname;
|
||||||
@ -103,11 +112,20 @@ exports.update = async (req, res) => {
|
|||||||
const currency = req.body.currency;
|
const currency = req.body.currency;
|
||||||
const is_featured = req.body.is_featured === undefined ? undefined : (req.body.is_featured === 'true' || req.body.is_featured === true);
|
const is_featured = req.body.is_featured === undefined ? undefined : (req.body.is_featured === 'true' || req.body.is_featured === true);
|
||||||
const state = req.body.state === undefined ? undefined : (req.body.state === 'false' || req.body.state === false ? false : true);
|
const state = req.body.state === undefined ? undefined : (req.body.state === 'false' || req.body.state === false ? false : true);
|
||||||
|
const removePicture = req.body.removePicture === 'true';
|
||||||
|
|
||||||
let object_storage_id;
|
let object_storage_id;
|
||||||
let original_filename;
|
let original_filename;
|
||||||
let uploadedKey = null;
|
let uploadedKey = null;
|
||||||
if (req.file) {
|
if (req.file) {
|
||||||
|
const allowedMime = ['image/jpeg','image/png','image/webp'];
|
||||||
|
if (!allowedMime.includes(req.file.mimetype)) {
|
||||||
|
return res.status(400).json({ error: 'Invalid image type. Allowed: JPG, PNG, WebP' });
|
||||||
|
}
|
||||||
|
const maxBytes = 10 * 1024 * 1024; // 10MB
|
||||||
|
if (req.file.size > maxBytes) {
|
||||||
|
return res.status(400).json({ error: 'Image exceeds 10MB limit' });
|
||||||
|
}
|
||||||
const s3 = new S3Client({
|
const s3 = new S3Client({
|
||||||
region: process.env.EXOSCALE_REGION,
|
region: process.env.EXOSCALE_REGION,
|
||||||
endpoint: process.env.EXOSCALE_ENDPOINT,
|
endpoint: process.env.EXOSCALE_ENDPOINT,
|
||||||
@ -117,7 +135,7 @@ exports.update = async (req, res) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const key = `coffee/products/${Date.now()}_${req.file.originalname}`;
|
const key = `coffee/products/${Date.now()}_${req.file.originalname}`;
|
||||||
await s3.send(new PutObjectCommand({ Bucket: process.env.EXOSCALE_BUCKET, Key: key, Body: req.file.buffer, ContentType: req.file.mimetype }));
|
await s3.send(new PutObjectCommand({ Bucket: process.env.EXOSCALE_BUCKET, Key: key, Body: req.file.buffer, ContentType: req.file.mimetype, ACL: 'public-read' }));
|
||||||
object_storage_id = key;
|
object_storage_id = key;
|
||||||
original_filename = req.file.originalname;
|
original_filename = req.file.originalname;
|
||||||
uploadedKey = key;
|
uploadedKey = key;
|
||||||
@ -127,6 +145,29 @@ exports.update = async (req, res) => {
|
|||||||
const current = await CoffeeService.get(id);
|
const current = await CoffeeService.get(id);
|
||||||
if (!current) return res.status(404).json({ error: 'Not found' });
|
if (!current) return res.status(404).json({ error: 'Not found' });
|
||||||
|
|
||||||
|
// If removePicture requested and no new file uploaded, clear existing object_storage_id
|
||||||
|
if (removePicture && !object_storage_id) {
|
||||||
|
object_storage_id = null;
|
||||||
|
original_filename = null;
|
||||||
|
// Delete previous object if exists
|
||||||
|
if (current && current.object_storage_id) {
|
||||||
|
try {
|
||||||
|
const s3del = new S3Client({
|
||||||
|
region: process.env.EXOSCALE_REGION,
|
||||||
|
endpoint: process.env.EXOSCALE_ENDPOINT,
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: process.env.EXOSCALE_ACCESS_KEY,
|
||||||
|
secretAccessKey: process.env.EXOSCALE_SECRET_KEY,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await s3del.send(new DeleteObjectCommand({ Bucket: process.env.EXOSCALE_BUCKET, Key: current.object_storage_id }));
|
||||||
|
logger.info('[CoffeeController.update] removed existing picture', { id });
|
||||||
|
} catch (delErr) {
|
||||||
|
logger.warn('[CoffeeController.update] remove existing picture failed', { id, msg: delErr.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const updated = await CoffeeService.update(id, {
|
const updated = await CoffeeService.update(id, {
|
||||||
title: title ?? current.title,
|
title: title ?? current.title,
|
||||||
description: description ?? current.description,
|
description: description ?? current.description,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user