const express = require('express'); const passport = require('passport'); const bodyParser = require('body-parser'); const services = require('../services/file'); const router = express.Router(); // JSON body parser that ONLY parses application/json content-type // This prevents errors when binary data is sent or no body is present const jsonParser = bodyParser.json({ limit: '1mb', type: (req) => { const contentType = req.headers['content-type'] || ''; return contentType.includes('application/json'); }, }); router.get('/download', (req, res) => { services.downloadFile(req, res); }); // POST /api/file/presign - Generate presigned URLs for multiple assets router.post('/presign', jsonParser, async (req, res) => { const { urls } = req.body || {}; if (!Array.isArray(urls) || urls.length === 0) { return res.status(400).json({ error: 'urls array required' }); } if (urls.length > 50) { return res.status(400).json({ error: 'Maximum 50 URLs per request' }); } // Validate that all URLs are strings const invalidUrls = urls.filter((url) => typeof url !== 'string' || !url.trim()); if (invalidUrls.length > 0) { return res.status(400).json({ error: 'All URLs must be non-empty strings' }); } try { const presignedUrls = await services.generatePresignedUrls(urls); res.json({ presignedUrls }); } catch (error) { console.error('Failed to generate presigned URLs', error); res.status(500).json({ error: 'Failed to generate presigned URLs' }); } }); router.post('/upload/:table/:field', passport.authenticate('jwt', {session: false}), (req, res) => { const fileName = `${req.params.table}/${req.params.field}`; services.uploadFile(fileName, req, res); }); router.post( '/upload-sessions/init', passport.authenticate('jwt', { session: false }), jsonParser, (req, res) => { services.initUploadSession(req, res); }, ); router.get( '/upload-sessions/:sessionId', passport.authenticate('jwt', { session: false }), (req, res) => { services.getUploadSession(req, res); }, ); // Chunk upload - NO body parser, raw stream is read directly by uploadChunk router.put( '/upload-sessions/:sessionId/chunks/:chunkIndex', passport.authenticate('jwt', { session: false }), (req, res) => { services.uploadChunk(req, res); }, ); // Finalize - NO body parser needed, only uses req.params.sessionId router.post( '/upload-sessions/:sessionId/finalize', passport.authenticate('jwt', { session: false }), (req, res) => { services.finalizeUploadSession(req, res); }, ); module.exports = router;