Resolve merge conflicts for video uploads and processing
This commit is contained in:
@@ -76,12 +76,15 @@ const upload = multer({
|
||||
},
|
||||
fileFilter: (req, file, cb) => {
|
||||
// Accept images and common video formats with proper validation
|
||||
const allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp', 'video/mp4', 'video/quicktime', 'video/webm'];
|
||||
const allowedMimeTypes = [
|
||||
'image/jpeg', 'image/png', 'image/webp',
|
||||
'video/mp4', 'video/webm', 'video/quicktime', 'video/x-msvideo'
|
||||
];
|
||||
|
||||
if (validateFileType(file.originalname, file.mimetype, allowedMimeTypes)) {
|
||||
return cb(null, true);
|
||||
} else {
|
||||
cb(new Error('Only JPEG, PNG, WebP images or MP4/MOV/WEBM videos are allowed'));
|
||||
cb(new Error('Only JPEG, PNG, WebP images and MP4, WebM, MOV, AVI videos are allowed'));
|
||||
}
|
||||
},
|
||||
// Add abort on limit to stop processing when limits are exceeded
|
||||
@@ -90,8 +93,12 @@ const upload = multer({
|
||||
|
||||
// Create content validator middleware
|
||||
const validateUploadContent = createFileUploadValidator({
|
||||
allowedTypes: ['image/jpeg', 'image/png', 'image/webp', 'video/mp4', 'video/quicktime', 'video/webm'],
|
||||
maxFileSize: 50 * 1024 * 1024,
|
||||
allowedTypes: [
|
||||
'image/jpeg', 'image/png', 'image/webp',
|
||||
'video/mp4', 'video/webm', 'video/quicktime', 'video/x-msvideo'
|
||||
],
|
||||
// 10GB per file to accommodate large videos; overall limits enforced elsewhere
|
||||
maxFileSize: 10 * 1024 * 1024 * 1024,
|
||||
validateContent: true
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
const { db } = require('../database/db');
|
||||
const { generateThumbnail, generateVideoPlaceholder } = require('./imageProcessor');
|
||||
const { processUploadedVideo } = require('./videoProcessor');
|
||||
const { generatePhotoFilename } = require('../utils/filenameSanitizer');
|
||||
const { isVideoMimeType } = require('../utils/fileSecurityUtils');
|
||||
const mime = require('mime-types');
|
||||
@@ -155,10 +156,21 @@ async function processUploadedPhotos(files, eventId, uploadedBy = 'admin', categ
|
||||
}
|
||||
}
|
||||
|
||||
// Generate thumbnail or placeholder
|
||||
// Generate thumbnail and metadata
|
||||
let thumbnailPath = null;
|
||||
let videoMetadata = null;
|
||||
if (isVideo) {
|
||||
thumbnailPath = await generateVideoPlaceholder(newFilename);
|
||||
const thumbnailDir = path.join(getStoragePath(), 'thumbnails');
|
||||
await fs.mkdir(thumbnailDir, { recursive: true });
|
||||
const videoThumbnailPath = path.join(thumbnailDir, `thumb_${newFilename.replace(/\.[^.]+$/, '.jpg')}`);
|
||||
try {
|
||||
const result = await processUploadedVideo(newPath, videoThumbnailPath);
|
||||
videoMetadata = result?.metadata || null;
|
||||
thumbnailPath = path.relative(getStoragePath(), videoThumbnailPath);
|
||||
} catch (videoErr) {
|
||||
console.error('Failed to process uploaded video, falling back to placeholder:', videoErr.message);
|
||||
thumbnailPath = await generateVideoPlaceholder(newFilename);
|
||||
}
|
||||
} else {
|
||||
thumbnailPath = await generateThumbnail(newPath);
|
||||
}
|
||||
@@ -173,32 +185,25 @@ async function processUploadedPhotos(files, eventId, uploadedBy = 'admin', categ
|
||||
const clientName = trx?.client?.config?.client;
|
||||
const supportsReturning = ['pg', 'postgres', 'postgresql'].includes(clientName);
|
||||
|
||||
const photoData = {
|
||||
event_id: eventId,
|
||||
filename: newFilename,
|
||||
path: relativePath,
|
||||
thumbnail_path: relativeThumbPath,
|
||||
type: photoType,
|
||||
size_bytes: file.size,
|
||||
uploaded_by: uploadedBy,
|
||||
source_origin: 'managed',
|
||||
mime_type: resolvedMime,
|
||||
media_type: isVideo ? 'video' : 'photo'
|
||||
};
|
||||
|
||||
if (supportsReturning) {
|
||||
insertResult = await trx('photos')
|
||||
.insert({
|
||||
event_id: eventId,
|
||||
filename: newFilename,
|
||||
path: relativePath,
|
||||
thumbnail_path: relativeThumbPath,
|
||||
type: photoType,
|
||||
size_bytes: file.size,
|
||||
uploaded_by: uploadedBy,
|
||||
source_origin: 'managed',
|
||||
mime_type: resolvedMime
|
||||
})
|
||||
.insert(photoData)
|
||||
.returning('id');
|
||||
} else {
|
||||
insertResult = await trx('photos').insert({
|
||||
event_id: eventId,
|
||||
filename: newFilename,
|
||||
path: relativePath,
|
||||
thumbnail_path: relativeThumbPath,
|
||||
type: photoType,
|
||||
size_bytes: file.size,
|
||||
uploaded_by: uploadedBy,
|
||||
source_origin: 'managed',
|
||||
mime_type: resolvedMime
|
||||
});
|
||||
insertResult = await trx('photos').insert(photoData);
|
||||
}
|
||||
|
||||
const insertedId = Array.isArray(insertResult)
|
||||
|
||||
Reference in New Issue
Block a user