diff --git a/apps/server/src/modules/filesystem/controller.ts b/apps/server/src/modules/filesystem/controller.ts index f85d883..6b1b17c 100644 --- a/apps/server/src/modules/filesystem/controller.ts +++ b/apps/server/src/modules/filesystem/controller.ts @@ -122,13 +122,22 @@ export class FilesystemController { const totalChunks = request.headers["x-total-chunks"] as string; const chunkSize = request.headers["x-chunk-size"] as string; const totalSize = request.headers["x-total-size"] as string; - const fileName = request.headers["x-file-name"] as string; + const encodedFileName = request.headers["x-file-name"] as string; const isLastChunk = request.headers["x-is-last-chunk"] as string; - if (!fileId || !chunkIndex || !totalChunks || !chunkSize || !totalSize || !fileName) { + if (!fileId || !chunkIndex || !totalChunks || !chunkSize || !totalSize || !encodedFileName) { return null; } + // Decode the base64-encoded filename to handle UTF-8 characters + let fileName: string; + try { + fileName = decodeURIComponent(escape(Buffer.from(encodedFileName, "base64").toString("binary"))); + } catch (error) { + // Fallback to the encoded value if decoding fails (for backward compatibility) + fileName = encodedFileName; + } + const metadata = { fileId, chunkIndex: parseInt(chunkIndex, 10), diff --git a/apps/web/src/utils/chunked-upload.ts b/apps/web/src/utils/chunked-upload.ts index 50104c2..e23b001 100644 --- a/apps/web/src/utils/chunked-upload.ts +++ b/apps/web/src/utils/chunked-upload.ts @@ -157,6 +157,10 @@ export class ChunkedUploader { url: string; signal?: AbortSignal; }): Promise { + // Encode filename as base64 to handle UTF-8 characters in HTTP headers + // This prevents errors when setting headers with non-ASCII characters + const encodedFileName = btoa(unescape(encodeURIComponent(fileName))); + const headers = { "Content-Type": "application/octet-stream", "X-File-Id": fileId, @@ -164,7 +168,7 @@ export class ChunkedUploader { "X-Total-Chunks": totalChunks.toString(), "X-Chunk-Size": chunkSize.toString(), "X-Total-Size": totalSize.toString(), - "X-File-Name": fileName, + "X-File-Name": encodedFileName, "X-Is-Last-Chunk": isLastChunk.toString(), };