fix: encode unicode filenames in Content-Disposition headers

Filenames with Romanian characters (Ș, Ț, etc.) caused ByteString errors.
Also pass original filename through to extreme mode response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-13 20:50:37 +02:00
parent 4b5d3bd498
commit 87ac81c6c9
2 changed files with 5 additions and 4 deletions
+1 -1
View File
@@ -195,7 +195,7 @@ export async function POST(req: NextRequest) {
status: 200, status: 200,
headers: { headers: {
"Content-Type": "application/pdf", "Content-Type": "application/pdf",
"Content-Disposition": `attachment; filename="${upload.filename.replace(/\.pdf$/i, "-comprimat.pdf")}"`, "Content-Disposition": `attachment; filename="${encodeURIComponent(upload.filename.replace(/\.pdf$/i, "-comprimat.pdf"))}"`,
"X-Original-Size": String(originalSize), "X-Original-Size": String(originalSize),
"X-Compressed-Size": String(compressedSize), "X-Compressed-Size": String(compressedSize),
}, },
+4 -3
View File
@@ -42,6 +42,7 @@ function streamFileResponse(
filePath: string, filePath: string,
originalSize: number, originalSize: number,
compressedSize: number, compressedSize: number,
filename: string,
): NextResponse { ): NextResponse {
const nodeStream = createReadStream(filePath); const nodeStream = createReadStream(filePath);
const webStream = Readable.toWeb(nodeStream) as ReadableStream; const webStream = Readable.toWeb(nodeStream) as ReadableStream;
@@ -51,7 +52,7 @@ function streamFileResponse(
headers: { headers: {
"Content-Type": "application/pdf", "Content-Type": "application/pdf",
"Content-Length": String(compressedSize), "Content-Length": String(compressedSize),
"Content-Disposition": 'attachment; filename="optimized.pdf"', "Content-Disposition": `attachment; filename="${encodeURIComponent(filename)}"`,
"X-Original-Size": String(originalSize), "X-Original-Size": String(originalSize),
"X-Compressed-Size": String(compressedSize), "X-Compressed-Size": String(compressedSize),
}, },
@@ -128,13 +129,13 @@ export async function POST(req: NextRequest) {
// Stream result from disk — if bigger, stream original // Stream result from disk — if bigger, stream original
if (compressedSize >= originalSize) { if (compressedSize >= originalSize) {
return streamFileResponse(inputPath, originalSize, originalSize); return streamFileResponse(inputPath, originalSize, originalSize, upload.filename);
} }
// NOTE: cleanup is deferred — we can't delete files while streaming. // NOTE: cleanup is deferred — we can't delete files while streaming.
// The files will be cleaned up by the OS temp cleaner or on next request. // The files will be cleaned up by the OS temp cleaner or on next request.
// For immediate cleanup, we'd need to buffer, but that defeats the purpose. // For immediate cleanup, we'd need to buffer, but that defeats the purpose.
return streamFileResponse(outputPath, originalSize, compressedSize); return streamFileResponse(outputPath, originalSize, compressedSize, upload.filename);
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : "Unknown error"; const message = err instanceof Error ? err.message : "Unknown error";
console.error(`[compress-pdf] Error:`, message); console.error(`[compress-pdf] Error:`, message);