forked from wangziqi/gongxue-base
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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user