Safari 12 Won't Download a PDF blob
Asked Answered
D

2

12

This code is used to download a pdf via blob. It works fine on every browser except Safari 12 for macOS and iOS. Even Safari 11 works. When I run the code the very first time, it works fine, but every time after that it gives me "WebKitBlobResource error 1"

function downloadFileFromBlob(fileBlob, fileName) {
    if (/\bMSIE\b|\bTrident\b/.test($window.navigator.userAgent)) {
        $window.navigator.msSaveOrOpenBlob(fileBlob, fileName);
    } else {
        var fileURL = $window.URL.createObjectURL(fileBlob);
        createDownloadElementAndClick(fileURL, fileName);
    }
}

function createDownloadElementAndClick(fileURL, fileName) {
    var anchorElement = $window.document.createElement('a');
    anchorElement.href = fileURL;
    anchorElement.target = '_blank';
    anchorElement.download = fileName;
    var event = $window.document.createEvent("MouseEvents");
    event.initEvent("click", true, false);
    anchorElement.dispatchEvent(event);
}
Declass answered 29/10, 2018 at 15:25 Comment(1)
If anyone is still facing this issue check this. πŸ‘¨β€πŸ’» https://mcmap.net/q/57272/-unable-to-download-pdf-blob-url-on-safari – Dowery
M
6

It seems that it is the target = "_blank" that is not working. I have replaced it with _self, which apparently solved the problem. I found this when I had the same issue.

If someone has a idea on why we cannot use _blank I would love to hear that.

Mears answered 16/11, 2018 at 13:5 Comment(2)
Given that only blobURIs are concerned by this _blank restriction, (dataURI seem to works fine), I'd say it's part of a bigger restriction where even window.open(blobURI) gets blocked. – Arnett
Attempting a solution to this as well, problem I have is when I use a.target = '_self', Chrome no longer names the blob download with filename defined in the download="" attribute... – Novosibirsk
I
6

Apparently this is a Safari 12 bug that sometimes happens. It's not fixed by target = "_self", which pertains to a different regression bug.

Until the bug is fixed, the ugly workaround is:

  1. Send the blob to the server which saves the file remotely.
  2. Download the remote file.

Javascript Code

   async createDownloadElementAndClick(blob, fileName) {
            let options = {
                method:"POST",
                body:blob
            };

            await fetch(`https://example.com/upload.php`, options);

            window.open(`https://example.com/download.php?${fileName}`, "_self");
    }

PHP Code

In upload.php:

<?php    
// add any authentication code as necessary here


    // gets entire POST body
    $data = file_get_contents('php://input');

    $filename = "temp/download.pdf";
    // write the data out to the file
    $fp = fopen($filename, 'wb');

    fwrite($fp, $data);
    fclose($fp);
?>

In download.php:

<?php
    ob_start();
    $file = $_SERVER["QUERY_STRING"];

    // This is the line that tells Safari to download the file instead of opening it
    header("Content-disposition: attachment; filename=$file");
    header("Content-type: application/pdf", false);
    readfile("temp/download.pdf");

    ob_flush();
    // This deletes the pdf so there is little chance of contaminating the next call
    unlink("temp/download.pdf");
?>
Ianthe answered 6/5, 2019 at 9:16 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.