fix(archive): serve student attachments securely

Download attachments through authenticated API requests, support configurable upload paths, validate resolved file locations, and retain compatibility with legacy stored paths.
This commit is contained in:
2026-07-10 14:11:47 +08:00
parent 55881863c1
commit 1ca4a4d185
3 changed files with 68 additions and 9 deletions

View File

@@ -10,9 +10,11 @@ import {
Request,
UseInterceptors,
UploadedFile,
Res,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Request as ExpressRequest } from 'express';
import type { Request as ExpressRequest, Response } from 'express';
import * as fs from 'fs';
import { ArchiveReportService } from './archive-report.service';
import { ArchiveService } from './archive.service';
import {
@@ -321,6 +323,23 @@ export class ArchiveController {
return result;
}
@Get(':studentId/attachments/:id')
@RequirePermission('student:view')
async downloadAttachment(
@Param('studentId') studentId: string,
@Param('id') id: string,
@Res() res: Response,
) {
const { fullPath, fileName, mimeType } = await this.archiveService.getAttachmentFile(+studentId, +id);
res.setHeader('Content-Type', mimeType);
res.setHeader(
'Content-Disposition',
`inline; filename="${encodeURIComponent(fileName)}"`,
);
const stream = fs.createReadStream(fullPath);
stream.pipe(res);
}
@Delete('attachments/:id')
@RequirePermission('student:edit')
async deleteAttachment(@Param('id') id: string, @Request() req: AuthenticatedRequest) {