90 lines
2.5 KiB
JavaScript

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;