feat: implement segment-based PDF download functionality with a dedicated UI for multi-page export
Build and Push Multi-Platform Images / build-and-push (push) Successful in 34s

This commit is contained in:
2026-05-06 09:46:23 +02:00
parent e08a5697f0
commit 415f8bbcf3
5 changed files with 162 additions and 29 deletions
@@ -176,14 +176,15 @@ export class InboxController {
await this.inboxService.updateSource(id, body.source, preferredUsername);
}
@Get(':id/download')
async download(
@Post(':id/download-segment')
async downloadSegment(
@Param('id') id: string,
@Body() body: { pages: number[] },
@Request() req: any,
@Res({ passthrough: true }) res: Response,
): Promise<StreamableFile> {
const preferredUsername: string | null = req.user?.preferredUsername ?? null;
const { buffer, filename } = await this.inboxService.getEditedPdfBuffer(id, preferredUsername);
const { buffer, filename } = await this.inboxService.getSegmentPdfBuffer(id, preferredUsername, body.pages ?? []);
const { Readable } = await import('stream');
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(filename)}"`);
+7 -10
View File
@@ -15,7 +15,7 @@ import {
type InboxSource,
} from '../database/entities/inbox-document.entity';
import { MailService } from '../postprocessing/mail.service';
import { applyEditsToTemp, cleanupTemp } from '../inbox-postprocessor/edit-applier';
import { applyEditsToTemp, cleanupTemp, buildSegmentBuffer } from '../inbox-postprocessor/edit-applier';
export interface InboxFile {
id: string;
@@ -253,19 +253,16 @@ export class InboxService {
return this.barcodeScanner.scanRegion(doc, pdfPath, page, x, y, w, h);
}
async getEditedPdfBuffer(
async getSegmentPdfBuffer(
id: string,
preferredUsername: string | null,
pages: number[],
): Promise<{ buffer: Buffer; filename: string }> {
const { doc, pdfPath } = await this.resolveDocument(id, preferredUsername);
let tmpPath: string | null = null;
try {
tmpPath = await applyEditsToTemp(doc, pdfPath);
const buffer = await fs.readFile(tmpPath);
return { buffer, filename: doc.OriginalName };
} finally {
await cleanupTemp(tmpPath);
}
const deleted = new Set(doc.DeletedPages ?? []);
const safePages = pages.filter((p) => p >= 1 && p <= doc.PageCount && !deleted.has(p));
const buffer = await buildSegmentBuffer(doc, pdfPath, safePages);
return { buffer, filename: doc.OriginalName };
}
async sendAsEmail(