diff --git a/apps/browser/src/platform/popup/services/browser-file-download.service.ts b/apps/browser/src/platform/popup/services/browser-file-download.service.ts index ec04adac2a..a30c7fe02c 100644 --- a/apps/browser/src/platform/popup/services/browser-file-download.service.ts +++ b/apps/browser/src/platform/popup/services/browser-file-download.service.ts @@ -15,23 +15,9 @@ export class BrowserFileDownloadService implements FileDownloadService { download(request: FileDownloadRequest): void { const builder = new FileDownloadBuilder(request); if (BrowserApi.isSafariApi) { - let data: BlobPart = null; - if (builder.blobOptions.type === "text/plain" && typeof request.blobData === "string") { - data = request.blobData; - } else { - data = Utils.fromBufferToB64(request.blobData as ArrayBuffer); - } - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - SafariApp.sendMessageToApp( - "downloadFile", - JSON.stringify({ - blobData: data, - blobOptions: request.blobOptions, - fileName: request.fileName, - }), - true, - ); + // Handle Safari download asynchronously to allow Blob conversion + // This function can't be async because the interface is not async + void this.downloadSafari(request, builder); } else { const a = window.document.createElement("a"); a.href = URL.createObjectURL(builder.blob); @@ -41,4 +27,31 @@ export class BrowserFileDownloadService implements FileDownloadService { window.document.body.removeChild(a); } } + + private async downloadSafari( + request: FileDownloadRequest, + builder: FileDownloadBuilder, + ): Promise { + let data: string = null; + if (builder.blobOptions.type === "text/plain" && typeof request.blobData === "string") { + data = request.blobData; + } else if (request.blobData instanceof Blob) { + // Convert Blob to ArrayBuffer first, then to Base64 + const arrayBuffer = await request.blobData.arrayBuffer(); + data = Utils.fromBufferToB64(arrayBuffer); + } else { + // Already an ArrayBuffer + data = Utils.fromBufferToB64(request.blobData as ArrayBuffer); + } + + await SafariApp.sendMessageToApp( + "downloadFile", + JSON.stringify({ + blobData: data, + blobOptions: request.blobOptions, + fileName: request.fileName, + }), + true, + ); + } } diff --git a/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift b/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift index 54e9161132..dad1e6855f 100644 --- a/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift +++ b/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift @@ -69,8 +69,8 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { if let url = panel.url { do { let fileManager = FileManager.default - if !fileManager.fileExists(atPath: url.absoluteString) { - fileManager.createFile(atPath: url.absoluteString, contents: Data(), + if !fileManager.fileExists(atPath: url.path) { + fileManager.createFile(atPath: url.path, contents: Data(), attributes: nil) } try data.write(to: url)