Chỉnh sửa phần upload ảnh

This commit is contained in:
2026-06-09 11:06:25 +07:00
parent 913867720f
commit 2fba77d50c
10 changed files with 171 additions and 27 deletions
+28 -17
View File
@@ -15,6 +15,7 @@ const { protect, optionalAuth } = require('../middlewares/authMiddleware');
const { verifyReferer, setNoCacheHeaders } = require('../middlewares/securityMiddleware');
const { resizeTo8K } = require('../utils/imageHelper');
const { getGPSCoordinates, injectGPSCoordinates } = require('../utils/exifHelper');
const { imageQueue } = require('./imageQueue');
const router = express.Router();
@@ -37,11 +38,16 @@ const storage = multer.diskStorage({
const upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
// Only accept images
if (file.mimetype.startsWith('image/')) {
// Chỉ chấp nhận các định dạng ảnh phổ biến đã được xử lý (Stitched)
const filetypes = /jpeg|jpg|png/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype) ||
file.mimetype === 'application/octet-stream'; // Đôi khi trình duyệt gửi JPG dưới dạng octet-stream
if (mimetype && extname) {
cb(null, true);
} else {
cb(new Error('Only image files are allowed!'), false);
cb(new Error('Chỉ chấp nhận các định dạng ảnh JPEG, PNG, DNG hoặc INSP!'), false);
}
}
});
@@ -93,21 +99,14 @@ router.post('/scenes', protect, uploadSinglePanorama, async (req, res) => {
const tempFilePath = req.file.path;
const processedFileName = `processed_${req.file.filename}.jpg`;
const processedFilePath = path.join(uploadDir, processedFileName);
// Lấy tọa độ GPS gốc từ ảnh vừa upload trước khi nén/xử lý
// Lấy tọa độ GPS gốc từ metadata
const originalGPS = await getGPSCoordinates(tempFilePath);
// Thực hiện xử lý ảnh tuần tự để đảm bảo file được tạo thành công trước khi lưu DB
// 1. Resize to 8K (Sẽ convert từ DNG sang JPG nếu sharp hỗ trợ libraw, nếu không sẽ báo lỗi)
await resizeTo8K(tempFilePath, processedFilePath);
// 2. Inject GPS vào file JPG vừa tạo
await injectGPSCoordinates(processedFilePath, latitude, longitude);
// 3. Cleanup temp file (file gốc dng)
if (fs.existsSync(tempFilePath)) fs.unlinkSync(tempFilePath);
const ext = path.extname(req.file.originalname).toLowerCase();
// 5. Save Asset to DB
const asset = new Asset({
filePath: processedFilePath,
filePath: tempFilePath, // Tạm thời dùng file gốc cho đến khi worker xử lý xong
uploadedBy: req.user._id,
coordinates: originalGPS ? { lat: originalGPS.lat, lng: originalGPS.lng } : { lat: latitude, lng: longitude }
});
@@ -133,7 +132,7 @@ router.post('/scenes', protect, uploadSinglePanorama, async (req, res) => {
const scene = new Scene({
name: title,
assetId: asset._id,
scene_url: processedFilePath, // Lưu đường dẫn ảnh trực tiếp
scene_url: tempFilePath, // Tạm thời
gps: {
lat: latitude,
lng: longitude
@@ -141,12 +140,24 @@ router.post('/scenes', protect, uploadSinglePanorama, async (req, res) => {
createdBy: req.user._id,
privacy: privacy || 'private',
shareToken,
sharedWith: parsedSharedWith
sharedWith: parsedSharedWith,
status: 'processing' // Đánh dấu đang xử lý
});
await scene.save();
// Đẩy tác vụ xử lý ảnh (Stitch + Resize) vào hàng đợi BullMQ
// Loại bỏ needsStitch và rotation vì người dùng đã stitch ảnh thủ công
await imageQueue.add('process-panorama', {
tempFilePath,
processedFilePath,
latitude,
longitude,
assetId: asset._id,
sceneId: scene._id
});
res.status(201).json({
message: 'Scene created successfully',
message: 'Scene đã được tạo! Ảnh đang được xử lý 8K ngầm...',
scene
});