Mini Utilities v0.2.0: extreme PDF compression (GS+qpdf), DWG→DXF, paste support, drag-drop layers

- Extreme PDF compression via direct Ghostscript + qpdf pipeline
  (PassThroughJPEGImages=false, QFactor 1.5, 72 DPI downsample)
- DWG→DXF converter via libredwg (Docker only)
- PDF unlock in-app via Stirling PDF proxy
- Removed PDF/A tab (unused)
- Paste (Ctrl+V) on all file drop zones
- Mouse drag-drop reordering on thermal layers
- Tabs reorganized into 2 visual rows
- Dockerfile: added ghostscript, qpdf, libredwg
This commit is contained in:
AI Assistant
2026-03-08 21:44:43 +02:00
parent 94b342e5ce
commit 12b7bca990
7 changed files with 1670 additions and 99 deletions
+46
View File
@@ -0,0 +1,46 @@
import { NextRequest, NextResponse } from "next/server";
const STIRLING_PDF_URL =
process.env.STIRLING_PDF_URL ?? "http://10.10.10.166:8087";
const STIRLING_PDF_API_KEY =
process.env.STIRLING_PDF_API_KEY ?? "cd829f62-6eef-43eb-a64d-c91af727b53a";
export async function POST(req: NextRequest) {
try {
const formData = await req.formData();
const res = await fetch(
`${STIRLING_PDF_URL}/api/v1/security/remove-password`,
{
method: "POST",
headers: { "X-API-KEY": STIRLING_PDF_API_KEY },
body: formData,
},
);
if (!res.ok) {
const text = await res.text().catch(() => res.statusText);
return NextResponse.json(
{ error: `Stirling PDF error: ${res.status}${text}` },
{ status: res.status },
);
}
const blob = await res.blob();
const buffer = Buffer.from(await blob.arrayBuffer());
return new NextResponse(buffer, {
status: 200,
headers: {
"Content-Type": "application/pdf",
"Content-Disposition": 'attachment; filename="unlocked.pdf"',
},
});
} catch (err) {
const message = err instanceof Error ? err.message : "Unknown error";
return NextResponse.json(
{ error: `Nu s-a putut contacta Stirling PDF: ${message}` },
{ status: 502 },
);
}
}