Make images draggable between products, add zoom
This commit is contained in:
@@ -10,6 +10,113 @@ const fs = require('fs');
|
||||
const uploadsDir = path.join('/var/www/html/inventory/uploads/products');
|
||||
fs.mkdirSync(uploadsDir, { recursive: true });
|
||||
|
||||
// Create a Map to track image upload times and their scheduled deletion
|
||||
const imageUploadMap = new Map();
|
||||
|
||||
// Function to schedule image deletion after 24 hours
|
||||
const scheduleImageDeletion = (filename, filePath) => {
|
||||
// Delete any existing timeout for this file
|
||||
if (imageUploadMap.has(filename)) {
|
||||
clearTimeout(imageUploadMap.get(filename).timeoutId);
|
||||
}
|
||||
|
||||
// Schedule deletion after 24 hours (24 * 60 * 60 * 1000 ms)
|
||||
const timeoutId = setTimeout(() => {
|
||||
console.log(`Auto-deleting image after 24 hours: ${filename}`);
|
||||
|
||||
// Check if file exists before trying to delete
|
||||
if (fs.existsSync(filePath)) {
|
||||
try {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`Successfully auto-deleted image: ${filename}`);
|
||||
} catch (error) {
|
||||
console.error(`Error auto-deleting image ${filename}:`, error);
|
||||
}
|
||||
} else {
|
||||
console.log(`File already deleted: ${filename}`);
|
||||
}
|
||||
|
||||
// Remove from tracking map
|
||||
imageUploadMap.delete(filename);
|
||||
}, 24 * 60 * 60 * 1000); // 24 hours
|
||||
|
||||
// Store upload time and timeout ID
|
||||
imageUploadMap.set(filename, {
|
||||
uploadTime: new Date(),
|
||||
timeoutId: timeoutId,
|
||||
filePath: filePath
|
||||
});
|
||||
};
|
||||
|
||||
// Function to clean up scheduled deletions on server restart
|
||||
const cleanupImagesOnStartup = () => {
|
||||
console.log('Checking for images to clean up...');
|
||||
|
||||
// Check if uploads directory exists
|
||||
if (!fs.existsSync(uploadsDir)) {
|
||||
console.log('Uploads directory does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
// Read all files in the directory
|
||||
fs.readdir(uploadsDir, (err, files) => {
|
||||
if (err) {
|
||||
console.error('Error reading uploads directory:', err);
|
||||
return;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
let countDeleted = 0;
|
||||
|
||||
files.forEach(filename => {
|
||||
const filePath = path.join(uploadsDir, filename);
|
||||
|
||||
// Get file stats
|
||||
try {
|
||||
const stats = fs.statSync(filePath);
|
||||
const fileCreationTime = stats.birthtime || stats.ctime; // birthtime might not be available on all systems
|
||||
const ageMs = now.getTime() - fileCreationTime.getTime();
|
||||
|
||||
// If file is older than 24 hours, delete it
|
||||
if (ageMs > 24 * 60 * 60 * 1000) {
|
||||
fs.unlinkSync(filePath);
|
||||
countDeleted++;
|
||||
console.log(`Deleted old image on startup: ${filename} (age: ${Math.round(ageMs / (60 * 60 * 1000))} hours)`);
|
||||
} else {
|
||||
// Schedule deletion for remaining time
|
||||
const remainingMs = (24 * 60 * 60 * 1000) - ageMs;
|
||||
console.log(`Scheduling deletion for ${filename} in ${Math.round(remainingMs / (60 * 60 * 1000))} hours`);
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (fs.existsSync(filePath)) {
|
||||
try {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`Successfully auto-deleted scheduled image: ${filename}`);
|
||||
} catch (error) {
|
||||
console.error(`Error auto-deleting scheduled image ${filename}:`, error);
|
||||
}
|
||||
}
|
||||
imageUploadMap.delete(filename);
|
||||
}, remainingMs);
|
||||
|
||||
imageUploadMap.set(filename, {
|
||||
uploadTime: fileCreationTime,
|
||||
timeoutId: timeoutId,
|
||||
filePath: filePath
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing file ${filename}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Cleanup completed: ${countDeleted} old images deleted, ${imageUploadMap.size} images scheduled for deletion`);
|
||||
});
|
||||
};
|
||||
|
||||
// Run cleanup on server start
|
||||
cleanupImagesOnStartup();
|
||||
|
||||
// Configure multer for file uploads
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
@@ -138,6 +245,9 @@ router.post('/upload-image', upload.single('image'), (req, res) => {
|
||||
const baseUrl = 'https://inventory.acot.site';
|
||||
const imageUrl = `${baseUrl}/uploads/products/${req.file.filename}`;
|
||||
|
||||
// Schedule this image for deletion in 24 hours
|
||||
scheduleImageDeletion(req.file.filename, filePath);
|
||||
|
||||
// Return success response with image URL
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
@@ -145,7 +255,7 @@ router.post('/upload-image', upload.single('image'), (req, res) => {
|
||||
fileName: req.file.filename,
|
||||
mimetype: req.file.mimetype,
|
||||
fullPath: filePath,
|
||||
message: 'Image uploaded successfully'
|
||||
message: 'Image uploaded successfully (will auto-delete after 24 hours)'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
@@ -173,6 +283,12 @@ router.delete('/delete-image', (req, res) => {
|
||||
// Delete the file
|
||||
fs.unlinkSync(filePath);
|
||||
|
||||
// Clear any scheduled deletion for this file
|
||||
if (imageUploadMap.has(filename)) {
|
||||
clearTimeout(imageUploadMap.get(filename).timeoutId);
|
||||
imageUploadMap.delete(filename);
|
||||
}
|
||||
|
||||
// Return success response
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
|
||||
Reference in New Issue
Block a user