feat: integrate preview generation into upload flow
Task 4: Upload Routes Extended - upload.js: Generate preview after single file upload - batchUpload.js: Generate previews for all batch uploads - Async preview generation (non-blocking response) - Auto-update preview_path in database after generation Task 5: Repository with preview_path - GroupRepository: Include preview_path in INSERT - getGroupById: Return previewPath in image objects - groupFormatter: Add previewPath to formatGroupDetail() - All queries now support preview_path column Task 6: API Endpoints Extended - Add PREVIEW_STATIC_DIRECTORY constant (/previews) - Serve preview images via express.static - All existing endpoints now return previewPath field - Fallback to filePath if preview not available (frontend)
This commit is contained in:
parent
940144cbf5
commit
661d6441ab
|
|
@ -2,6 +2,7 @@ const endpoints = {
|
|||
UPLOAD_STATIC_DIRECTORY: '/upload',
|
||||
UPLOAD_FILE: '/upload',
|
||||
UPLOAD_BATCH: '/upload/batch',
|
||||
PREVIEW_STATIC_DIRECTORY: '/previews',
|
||||
DOWNLOAD_FILE: '/download/:id',
|
||||
GET_GROUP: '/groups/:groupId',
|
||||
GET_ALL_GROUPS: '/groups',
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ class GroupRepository {
|
|||
if (groupData.images && groupData.images.length > 0) {
|
||||
for (const image of groupData.images) {
|
||||
await db.run(`
|
||||
INSERT INTO images (group_id, file_name, original_name, file_path, upload_order, file_size, mime_type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO images (group_id, file_name, original_name, file_path, upload_order, file_size, mime_type, preview_path)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, [
|
||||
groupData.groupId,
|
||||
image.fileName,
|
||||
|
|
@ -31,7 +31,8 @@ class GroupRepository {
|
|||
image.filePath,
|
||||
image.uploadOrder,
|
||||
image.fileSize || null,
|
||||
image.mimeType || null
|
||||
image.mimeType || null,
|
||||
image.previewPath || null
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +68,7 @@ class GroupRepository {
|
|||
fileName: img.file_name,
|
||||
originalName: img.original_name,
|
||||
filePath: img.file_path,
|
||||
previewPath: img.preview_path,
|
||||
uploadOrder: img.upload_order,
|
||||
fileSize: img.file_size,
|
||||
mimeType: img.mime_type
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const { endpoints } = require('../constants');
|
|||
const UploadGroup = require('../models/uploadGroup');
|
||||
const GroupRepository = require('../repositories/GroupRepository');
|
||||
const dbManager = require('../database/DatabaseManager');
|
||||
const ImagePreviewService = require('../services/ImagePreviewService');
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
|
@ -64,6 +65,37 @@ router.post(endpoints.UPLOAD_BATCH, async (req, res) => {
|
|||
});
|
||||
}
|
||||
|
||||
// Generate previews for all uploaded images asynchronously
|
||||
const previewDir = path.join(__dirname, '..', require('../constants').PREVIEW_FS_DIR);
|
||||
const uploadDir = path.join(__dirname, '..', require('../constants').UPLOAD_FS_DIR);
|
||||
|
||||
// Generate previews in background (don't wait)
|
||||
ImagePreviewService.generatePreviewsForGroup(
|
||||
processedFiles.map(f => ({ file_name: f.fileName, file_path: `/upload/${f.fileName}` })),
|
||||
uploadDir,
|
||||
previewDir
|
||||
).then(results => {
|
||||
const successCount = results.filter(r => r.success).length;
|
||||
console.log(`Preview generation completed: ${successCount}/${results.length} successful`);
|
||||
|
||||
// Update preview_path in database for successful previews
|
||||
results.forEach(async (result) => {
|
||||
if (result.success) {
|
||||
try {
|
||||
await dbManager.run(`
|
||||
UPDATE images
|
||||
SET preview_path = ?
|
||||
WHERE group_id = ? AND file_name = ?
|
||||
`, [result.previewPath, group.groupId, result.fileName]);
|
||||
} catch (err) {
|
||||
console.error(`Failed to update preview_path for ${result.fileName}:`, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error('Preview generation failed:', err);
|
||||
});
|
||||
|
||||
// Speichere Gruppe in SQLite
|
||||
await GroupRepository.createGroup({
|
||||
groupId: group.groupId,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
const generateId = require("shortid");
|
||||
const express = require('express');
|
||||
const { Router } = require('express');
|
||||
const { endpoints, UPLOAD_FS_DIR } = require('../constants');
|
||||
const { endpoints, UPLOAD_FS_DIR, PREVIEW_FS_DIR } = require('../constants');
|
||||
const path = require('path');
|
||||
const ImagePreviewService = require('../services/ImagePreviewService');
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Serve uploaded images via URL /upload but store files under data/images
|
||||
router.use(endpoints.UPLOAD_STATIC_DIRECTORY, express.static( path.join(__dirname, '..', UPLOAD_FS_DIR) ));
|
||||
|
||||
router.post(endpoints.UPLOAD_FILE, (req, res) => {
|
||||
// Serve preview images via URL /previews but store files under data/previews
|
||||
router.use(endpoints.PREVIEW_STATIC_DIRECTORY, express.static( path.join(__dirname, '..', PREVIEW_FS_DIR) ));
|
||||
|
||||
router.post(endpoints.UPLOAD_FILE, async (req, res) => {
|
||||
if(req.files === null){
|
||||
console.log('No file uploaded');
|
||||
return res.status(400).json({ msg: 'No file uploaded' });
|
||||
|
|
@ -22,14 +26,40 @@ router.post(endpoints.UPLOAD_FILE, (req, res) => {
|
|||
fileName = generateId() + '.' + fileEnding
|
||||
|
||||
const savePath = path.join(__dirname, '..', UPLOAD_FS_DIR, fileName);
|
||||
file.mv(savePath, err => {
|
||||
if(err) {
|
||||
console.error(err);
|
||||
return res.status(500).send(err);
|
||||
}
|
||||
|
||||
try {
|
||||
// Save the uploaded file
|
||||
await new Promise((resolve, reject) => {
|
||||
file.mv(savePath, err => {
|
||||
if(err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
res.json({ filePath: `${endpoints.UPLOAD_STATIC_DIRECTORY}/${fileName}`});
|
||||
});
|
||||
// Generate preview asynchronously (don't wait for it)
|
||||
const previewFileName = ImagePreviewService._getPreviewFileName(fileName);
|
||||
const previewPath = ImagePreviewService.getPreviewPath(previewFileName);
|
||||
|
||||
ImagePreviewService.generatePreview(savePath, previewPath)
|
||||
.then(result => {
|
||||
if (!result.success) {
|
||||
console.warn(`Preview generation failed for ${fileName}:`, result.error);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`Unexpected error during preview generation for ${fileName}:`, err);
|
||||
});
|
||||
|
||||
// Return immediately with file path
|
||||
res.json({
|
||||
filePath: `${endpoints.UPLOAD_STATIC_DIRECTORY}/${fileName}`,
|
||||
fileName: fileName
|
||||
});
|
||||
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
return res.status(500).send(err);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -29,6 +29,7 @@ function formatGroupDetail(groupRow, images) {
|
|||
fileName: img.file_name,
|
||||
originalName: img.original_name,
|
||||
filePath: img.file_path,
|
||||
previewPath: img.preview_path || null,
|
||||
uploadOrder: img.upload_order,
|
||||
fileSize: img.file_size || null,
|
||||
mimeType: img.mime_type || null
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user