diff --git a/server/src/routes/files.ts b/server/src/routes/files.ts index fdd70d84..6b5a041f 100644 --- a/server/src/routes/files.ts +++ b/server/src/routes/files.ts @@ -98,6 +98,13 @@ router.get('/:id/download', (req: Request, res: Response) => { if (!safe) return res.status(403).json({ error: 'Forbidden' }); if (!fs.existsSync(resolved)) return res.status(404).json({ error: 'File not found' }); + // Serve Apple Wallet passes inline with the canonical MIME type so Safari + // (iOS/macOS) hands them off to Wallet instead of downloading as a blob. + if (path.extname(resolved).toLowerCase() === '.pkpass') { + res.setHeader('Content-Type', 'application/vnd.apple.pkpass'); + res.setHeader('Content-Disposition', `inline; filename="${path.basename(file.original_name || resolved)}"`); + } + res.sendFile(resolved); }); diff --git a/server/src/services/fileService.ts b/server/src/services/fileService.ts index 288a58db..45f7cee6 100644 --- a/server/src/services/fileService.ts +++ b/server/src/services/fileService.ts @@ -11,7 +11,7 @@ import { TripFile } from '../types'; // --------------------------------------------------------------------------- export const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50 MB -export const DEFAULT_ALLOWED_EXTENSIONS = 'jpg,jpeg,png,gif,webp,heic,pdf,doc,docx,xls,xlsx,txt,csv'; +export const DEFAULT_ALLOWED_EXTENSIONS = 'jpg,jpeg,png,gif,webp,heic,pdf,doc,docx,xls,xlsx,txt,csv,pkpass'; export const BLOCKED_EXTENSIONS = ['.svg', '.html', '.htm', '.xml']; export const filesDir = path.join(__dirname, '../../uploads/files');