refactor(pdf-compress): replace Ghostscript with qpdf + iLovePDF API
Ghostscript -sDEVICE=pdfwrite fundamentally re-encodes fonts, causing garbled text regardless of parameters. This cannot be fixed. New approach: - Local: qpdf-only lossless structural optimization (5-30% savings, zero corruption risk — fonts and images completely untouched) - Cloud: iLovePDF API integration (auth → start → upload → process → download) with 3 levels (recommended/extreme/low), proper image recompression without font corruption Frontend: 3 modes (cloud recommended, cloud extreme, local lossless). Docker: ILOVEPDF_PUBLIC_KEY env var added. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1638,7 +1638,7 @@ function formatBytes(bytes: number) {
|
||||
|
||||
function PdfReducer() {
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [mode, setMode] = useState<"extreme" | "max" | "balanced">("extreme");
|
||||
const [mode, setMode] = useState<"cloud-extreme" | "cloud-recommended" | "local">("cloud-recommended");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
const [result, setResult] = useState<{
|
||||
@@ -1662,10 +1662,21 @@ function PdfReducer() {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append("fileInput", file);
|
||||
// All modes use the GS endpoint with a level parameter
|
||||
formData.append("level", mode === "extreme" ? "extreme" : mode === "max" ? "high" : "balanced");
|
||||
|
||||
const res = await fetch("/api/compress-pdf/extreme", {
|
||||
let endpoint: string;
|
||||
if (mode === "local") {
|
||||
// qpdf-only: lossless structural optimization
|
||||
endpoint = "/api/compress-pdf/extreme";
|
||||
} else {
|
||||
// iLovePDF cloud compression
|
||||
endpoint = "/api/compress-pdf/cloud";
|
||||
formData.append(
|
||||
"level",
|
||||
mode === "cloud-extreme" ? "extreme" : "recommended",
|
||||
);
|
||||
}
|
||||
|
||||
const res = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
@@ -1755,22 +1766,26 @@ function PdfReducer() {
|
||||
<select
|
||||
value={mode}
|
||||
onChange={(e) =>
|
||||
setMode(e.target.value as "extreme" | "max" | "balanced")
|
||||
setMode(e.target.value as "cloud-extreme" | "cloud-recommended" | "local")
|
||||
}
|
||||
className="mt-1 w-full rounded-md border bg-background px-3 py-2 text-sm"
|
||||
>
|
||||
<option value="extreme">
|
||||
Extremă — imagini 100 DPI, calitate scăzută
|
||||
<option value="cloud-recommended">
|
||||
☁️ iLovePDF — compresie recomandat
|
||||
</option>
|
||||
<option value="cloud-extreme">
|
||||
☁️ iLovePDF — compresie extremă
|
||||
</option>
|
||||
<option value="local">
|
||||
💻 Local — optimizare structurală (fără pierderi)
|
||||
</option>
|
||||
<option value="max">Puternică — imagini 150 DPI, calitate medie (recomandat)</option>
|
||||
<option value="balanced">Echilibrată — imagini 200 DPI, calitate bună</option>
|
||||
</select>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{mode === "extreme"
|
||||
? "Reduce maxim dimensiunea. Imaginile pot pierde detalii fine."
|
||||
: mode === "max"
|
||||
? "Balanță bună între dimensiune și calitate. Recomandat pentru majoritatea fișierelor."
|
||||
: "Pierdere minimă de calitate. Ideal pentru documente cu grafice detaliate."}
|
||||
{mode === "cloud-recommended"
|
||||
? "Compresie cloud cu calitate bună. Reduce semnificativ imaginile păstrând lizibilitatea."
|
||||
: mode === "cloud-extreme"
|
||||
? "Compresie maximă cloud. Imagini reduse agresiv — ideal pentru arhivare."
|
||||
: "Optimizare locală cu qpdf (lossless). Zero pierdere de calitate, reducere 5-30%."}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user