const express = require('express'); const multer = require('multer'); const { v4: uuidv4 } = require('uuid'); const path = require('path'); const fs = require('fs'); const helmet = require('helmet'); const compression = require('compression'); const rateLimit = require('express-rate-limit'); const app = express(); const PORT = 5000; app.set('trust proxy', 1); const uploadDir = path.join(__dirname, 'uploads'); const dbPath = path.join(__dirname, 'files.json'); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } if (!fs.existsSync(dbPath)) { fs.writeFileSync(dbPath, '[]'); } app.use( helmet({ crossOriginResourcePolicy: false, contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], scriptSrc: [ "'self'", "'unsafe-inline'", "'unsafe-eval'", "blob:" ], styleSrc: [ "'self'", "'unsafe-inline'" ], imgSrc: [ "'self'", "data:", "blob:" ] } } }) ); app.use(compression()); app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 })); app.use(express.json()); app.use(express.static( path.join(__dirname, 'public') )); app.use( '/files', express.static(uploadDir) ); const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, uploadDir); }, filename: (req, file, cb) => { const ext = path.extname(file.originalname); cb(null, uuidv4() + ext); } }); const upload = multer({ storage, limits: { fileSize: 500 * 1024 * 1024 } }); function formatFileSize(bytes){ const sizes = ['Bytes','KB','MB','GB']; if(bytes === 0){ return '0 Byte'; } const i = parseInt( Math.floor( Math.log(bytes) / Math.log(1024) ) ); return Math.round( bytes / Math.pow(1024,i) ) + ' ' + sizes[i]; } app.post( '/upload', upload.single('file'), (req, res) => { try { if (!req.file) { return res.status(400).json({ success: false, error: 'No file uploaded' }); } const expiresAt = Date.now() + (30 * 60 * 1000); const fileUrl = `${req.protocol}://${req.get('host')}/files/${req.file.filename}`; let db = []; if(fs.existsSync(dbPath)){ const raw = fs.readFileSync( dbPath, 'utf8' ); db = raw ? JSON.parse(raw) : []; } db.push({ id: uuidv4(), filename: req.file.filename, originalName: req.file.originalname, size: req.file.size, uploadedAt: Date.now(), expiresAt }); fs.writeFileSync( dbPath, JSON.stringify(db, null, 2) ); return res.json({ success: true, downloadLink: fileUrl, fileName: req.file.originalname, fileSize: formatFileSize(req.file.size), expiresIn: '30 minutes' }); } catch (err) { console.error(err); return res.status(500).json({ success: false, error: err.message }); } }); function cleanupOldFiles(){ const now = Date.now(); let db = []; if(fs.existsSync(dbPath)){ const raw = fs.readFileSync( dbPath, 'utf8' ); db = raw ? JSON.parse(raw) : []; } db = db.filter(file => { const filePath = path.join( uploadDir, file.filename ); if(now > file.expiresAt){ if(fs.existsSync(filePath)){ fs.unlinkSync(filePath); console.log( 'Deleted:', file.filename ); } return false; } return true; }); fs.writeFileSync( dbPath, JSON.stringify(db, null, 2) ); } setInterval( cleanupOldFiles, 60000 ); app.use((err, req, res, next) => { console.error(err); if ( err instanceof multer.MulterError ) { if ( err.code === 'LIMIT_FILE_SIZE' ) { return res.status(400).json({ success: false, error: 'File exceeds 500MB limit' }); } } return res.status(500).json({ success: false, error: 'Internal server error' }); }); app.listen(PORT, () => { console.log( 'TempShare running on port', PORT ); });