Search code examples
javascripthttp-status-code-404html2canvas

html2canvas Download Image Client-Side on iOS Safari


Fiddle/Pen: https://codepen.io/michaelsboost/pen/bGbLpbX

Problem: html2canvas error: Failed to load resource: the server responded with a status of 404 () html2canvas.js.map only shows on iOS Safari. However, it works perfectly fine on Desktop and Android.

Screenshot of Error:

enter image description here

Javascript:

// Variables
var str, startTime, imageURL, first, next,
    workoutlog = document.querySelector("[data-output=workoutlog]"),
    testString = "Date: 9:6:2019\nStart time: 3:10:57 PM\nObjective: 17 pushups a minute for 1 hour\nGoal: 1020 pushups in 1 hour\nCompleted: 1020 pushups\n60 minutes have gone by\n0 pushups remaining\n0 minutes remaining\nTimes Paused: 0\nFinished at: 4:10:56 PM",
    openInNewTab = function(url) {
      str = testString;
      str = str.substr(1, str.length);
      str = str.replace(/%20/g, " ");

      startTime = str.substring(0, str.indexOf('\\n'));
      first = str.indexOf('\\n');
      next  = str.indexOf('\\n', first + 1);
      dateTime  = startTime.replace(/Date: /g, "");
      startTime = str.substring(str.indexOf('Finished at: '));
      startTime  = startTime.replace(/Finished at: /g, "");

      var a = document.createElement("a");
      a.href = url;
      a.download = "workout_log " + dateTime + " " + startTime;
      a.click();
    };

// set sample log
workoutlog.innerHTML = testString.replace(/\n/g, "<br>");

// run html2canvas
html2canvas(document.querySelector(".grablog")).then(function(canvas) {
  // download canvas image
  imageURL = canvas.toDataURL();
  openInNewTab(imageURL);
});

Research:

  1. I know that because the script is right before the closing body tags adding DOMContentLoaded would be unnecessary as the content is already there. (I did however try it anyway just to see if it would solve the problem anyway which it didn't).
  2. I already know that the HTTP status code 404 indicates the server could not find the requested file or resource. However this is a DataURL image thus no server. I've searched Google for a few days to find a resolution relative to my problem but everything I find pertains to uploading the image on a server and saving it that way.

Questions:

  1. Why does the download work on desktop and android but not iOS?
  2. What work arounds are there that I can use to solve this problem for iOS that does not require uploading the image to a server?

Solution

  • After some research, I found that the reason the download attribute works on desktop and android but not iOS is because iOS doesn't have a file system. The alternative is to open the file on the browser with the proper mime type, so it can show its content (and the user can then manually download it if needed).
    source 1 source 2 source 3

    var img = new Image();
    img.crossOrigin = "Anonymous";
    img.id = "getshot";
    img.src = imageURL;
    document.body.appendChild(img);
    
    var a = document.createElement("a");
    a.href = getshot.src;
    a.download = "workout_log " + dateTime + " " + startTime + ".png";
    a.click();
    document.body.removeChild(img);