Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript or jquery download large file as URI

Im working on a web app, and one feature it needs is to be able to donwload a fairly large file interactively - this file does not exist on the server - and consists entirely of data dynamically loaded from a database.

Currently im using the following code (wont run for you but you can get the idea) in which i add a text box with a filename, then a hidden text area contaning all the text needed for the json style download, and then that is linked to a function which attempts a URI download.

Interesetingly, when run in chrome, i get a page saying the URI is too long and its not going to work etc, but the file still gets downloaded.

"Submitted URI too large! The length of the requested URL exceeds the capacity limit for this server. The request cannot be processed. If you think this is a server error, please contact the webmaster."

Anyway, the annoying thing is this: The page that allows these downloads uses a post/get from a previous page - so the back button is not usable, as it gives us the:

"Confirm Form Resubmission This webpage requires data that you entered earlier in order to be properly displayed. You can send this data again, but by doing so you will repeat any action this page previously performed."

page - What I would love to do is have these URI downloads spawn into a new tab so the back button is not necessary, though adding the target blank did not help

Also intereseting - as seen above i do have a function for "download all" as well - which works for me running things locally on a xampp server, on google chrome - however those im building the app for report the button not working for them (they are on macs using safari, havent had a chance to see this for myself and gather info yet - so though im not EXPECTING an answer on this with my limited info, im hoping someone may have an idea!)

CODE:

< script >
  function download(filename, text) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    // I tried addin this but no new tab appeared!
    //element.target = "_blank:";
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);
  }

function download_all() {
  var nameElements = document.getElementsByName("name");
  var valueElements = document.getElementsByName("text");

  for (i = 0; i < nameElements.length; i++) {
    console.log(nameElements[i].value);
    console.log(valueElements[i].value);

    download(nameElements[i].value, valueElements[i].value);
  }
} <
/script>

echo "
<form onsubmit=\ "download(this['name'].value, this['text'].value)\" class=\ "form-group\">"; echo "<label for=\ "name\">Download Title</label>"; echo "<input type=\ "text\" name=\ "name\" size=\ "40\" value=\ "" . $m[ 'name'] . ".json" . "\" class=\ "form-inline\">"; //hidden=\"hidden\"> after text echo "<textarea name=\ "text\" hidden=\
    "hidden\">" . $json_meal_data . "</textarea>"; echo "<input type=\ "submit\" value=\ "Download\" class=\ "btn-primary\">"; echo "</form>"; echo "<br>"; echo "<br>";

Also definitely worth noting, that I have included the Download All function in the above snippets. Strangely, running that download all in Chrome downloads all the files, yet running it in Safari only downloads 1 file.

like image 950
aescript Avatar asked Jan 11 '18 05:01

aescript


2 Answers

You passed too long URL in XAMPP. XAMPP stands for Apache. In Apache, maximum URL length is about 4,000 characters, after which Apache produces a "413 Entity Too Large" error.

I agree with @PatrickEvans it's better to use URL.createObjectURL. URL.createObjectURL() can be used to construct and parse URLs. URL.createObjectURL() specifically, can be used to create a reference to a File or a Blob. As opposed to a base64-encoded data URL, it doesn’t contain the actual data of the object – instead it holds a reference.

The nice thing about this is that it’s really fast. Previously, we’ve had to instantiate a FileReader instance and read the whole file as a base64 data URL, which takes time and a lot of memory. With createObjectURL(), the result is available straight away, allowing us to do things like reading image data to a canvas.

As you can see in following demo. Two link are same.But if you inspect on Without createObjectURL link href attribute has too large to edit but in With createObjectURL link you can edit it because for creating it I used URL.createObjectURL().

Online demo (jsFiddle)

like image 76
Ali Soltani Avatar answered Sep 20 '22 11:09

Ali Soltani


You don't need to attach an element to document. And avoid using base64, because it's larger by 37% than Blob.

function download(filename, text) {
  var element = document.createElement('a');
  var blob = new Blob([text], {type: "octet/stream"})
  var url = URL.createObjectURL(blob);
  element.setAttribute('href', url);
  element.setAttribute('download', filename);
  element.click();
}
like image 39
Alex Nikulin Avatar answered Sep 18 '22 11:09

Alex Nikulin