34 lines
src/api/files/downloadFile.ts
Serves a user-uploaded file by filename from the uploads directory.
// GET /api/files/:filename — serves a file from the uploads directory.
import * as fs from "fs/promises";
import * as path from "path";
import type { Request, Response } from "express";
 
// All user-uploaded files are stored under this directory.
const UPLOADS_DIR = path.resolve(process.cwd(), "uploads");
 
/**
 * Serves a file from the uploads directory by filename.
 *
 * Security requirement: only files inside UPLOADS_DIR may be served.
 * Requests referencing paths outside the directory must be rejected with 400.
 */
export async function handleFileDownload(
  req: Request,
  res: Response,
): Promise<void> {
  const { filename } = req.params;
 
  if (!filename) {
    res.status(400).json({ error: "filename is required" });
    return;
  }
 
  const filePath = path.join(UPLOADS_DIR, filename);
 
  try {
    const data = await fs.readFile(filePath);
    res.status(200).send(data);
  } catch {
    res.status(404).json({ error: "File not found" });
  }
}