How to download a file without using <a> element with download attribute or a server?
Asked Answered
C

6

13

According to caniuse the download attribute of <a> element is supported at Microsoft Edge build 10547+, but not IE or Safari.

How to download a file object without using <a> element with download attribute set or a server?

Chuvash answered 2/8, 2016 at 4:31 Comment(8)
You can check my answer here: #38524820 It gives exactly what you are looking for.Strikebreaker
@Strikebreaker See criteria at OP, .responseType was not defined at that point in browser development.Chuvash
are you looking for a solution for 2016-browser-compatible or 2017? :)Strikebreaker
@Strikebreaker Will not try to change the context of the original Question after the fact. See How to create an ArrayBuffer and data URI from Blob and File objects without FileReader? where posted an Answer that did not meet original criteria, though provided solution, Kaiido accurately pointed out the appropriate context.Chuvash
What do you mean without a "server"?Automatism
@jdc91 Without requesting the file from a server and without server responding with data having Content-Disposition header. Using the browser to offer the downloadChuvash
What will be the contents of the file. Better if you can state the whole story! Meanwhile, you can try developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURLAutomatism
@jdc91 See "Better if you can state the whole story!" See #38194105, https://mcmap.net/q/42128/-how-to-create-an-arraybuffer-and-data-uri-from-blob-and-file-objects-without-filereaderChuvash
B
18

There are a number of ways of triggering a download. Following are a few:

Use a form:

<form method="get" action="mydoc.doc">
<button type="submit">Download</button>
</form>

Use javascript:

<button type="submit" onclick="window.open('mydoc.doc')">Download</button>
Buttonball answered 2/8, 2016 at 4:48 Comment(3)
what if user has browser plugin which open mydoc.doc? then how it will be downloaded?Inactivate
A user can choose to save content they see via a browser plugin. However, you can't force a download from the front-end. See this: #8614225Buttonball
window.open("blob:xyz") still works well for me in 2023 here's the reference; developer.mozilla.org/en-US/docs/Web/API/Window/openAnklet
V
3

Although I support @LeoFarmer's answer, I would like to offer two "hackable" approaches:

  1. If the file is very small, you can use a with the href='data:[<mediatype>][;base64],<data>'.

    This could allow you to add content disposition in the mediatype, emulating an HTTP header. This hack is also not as portable as one might hope.

  2. On small to medium files, it's possible to download the file using AJAX, and then use the Javascript File API to prompt for file saving (the API doesn't support saving, but it's easy to convert the data to a data URL).

    If you want to avoid the Javascript File API, you can try emulating an anchor click, as suggested here.

Again, as pointed out by Leo Farmer, these solutions can't promise that the browser won't open the file in a new tab instead of saving it to the disk, but I think it's safe to say that all users will be able to gracefully degrade to a cmd+S or ctrl+S keyboard shortcut :-)

Volteface answered 9/8, 2017 at 3:9 Comment(0)
P
3

Use FileSaver.js

It supports all the commonly used browsers.

Just include:

<script type="text/javascript" src="FileSaver.min.js"></script>

and use it like:

var file = new File(["Hello, world!"], "hello world.txt", {type: "text/plain;charset=utf-8"});
saveAs(file);

Note: To make it work also in Safari < 6, Opera < 15 and FireFox < 20 you need to include Blob.js as a dependency.

Platinic answered 9/8, 2017 at 6:17 Comment(3)
Is File constructor available at the browsers mentioned at last sentence of Answer?Chuvash
No they don't. (caniuse.com/#search=File) But take a look at the documentation of FileSaver.js, there are other ways of saving it. I hope you'll find it helpful. :)Platinic
Amazing! It simply works, even with TypeScript and is probably the easiest way to do it in major browsers. I added "file-saver" to the "types" tsconfig option and used "saveAs" as a method anywhere in my project (needs to @ts-ignore the error in case of using it inside typescript modules). The minified version for distribution is here.Remediless
I
2

You may do this using both download attribute and jquery. download attribute don't support in ie and safari/ios. So you may use jquery to do that

 $('.download').click(function(e) {
    e.preventDefault();  //stop the browser from following
    window.location.href = 'uploads/file.doc';
});

<a href="no-script.html" class="download">Download</a>
Interchangeable answered 9/8, 2017 at 5:44 Comment(0)
C
1

You can use data URI data:[<mediatype>][;base64],<data> representation of file either created manually or utilizing FileReader(), .readAsDataURL(), with MIME type set to application/octet-stream, encodeURIComponent(), window.open()

<script>
  var file = "data:application/octet-stream,"
             + encodeURIComponent("<!DOCTYPE html>"
             + "<html><body>"
             + "<div>abc</div>"
             + "</body></html>");
  var saveFile = window.open(file, "_self");     
</script>

<script>
  var blob = new Blob(["abc"], {type:"text/plain"});
  var reader = new FileReader();
  reader.addEventListener("load", function(e) {
    // replace existing `MIME` type with `application/octet-stream`
    var file = "data:application/octet-stream;" 
                + e.target.result.split(/;/)[1];
    var saveFile = window.open(file, "_self");
  });
  reader.readAsDataURL(blob)
</script>

plnkr http://plnkr.co/edit/IS1OC0laRwL3BuuF9zay?p=preview

Chuvash answered 2/8, 2016 at 5:20 Comment(0)
R
-1

If you're using server-side then follow the form submission mechanism to render the page. In MVC we can use below code

Html

  @using (Html.BeginForm("GetAttachment", "User", FormMethod.Post))
                {

                    <button type="submit">Download</button>   
                }

MVC Controller

public ActionResult GetAttachment()
{
   string filename = "File.pdf";
string filepath = AppDomain.CurrentDomain.BaseDirectory + "/Path/To/File/" + filename;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = MimeMapping.GetMimeMapping(filepath);

var cd = new System.Net.Mime.ContentDisposition
{
    FileName = filename,
    Inline = true,
};

Response.AppendHeader("Content-Disposition", cd.ToString());

return File(filedata, contentType);
}
Reinhart answered 9/8, 2017 at 7:7 Comment(7)
"without using <a> element with download attribute or a server?"Chuvash
using form we are submitting the data to server and server return the file.Reinhart
A <form> does not need to be submitted to a server. The requirement of Question is to not use a serverChuvash
can I use $.fileDownload('/url/to/download.pdf'); attribute?Reinhart
Not sure what you mean?Chuvash
please refer this johnculviner.com/…Reinhart
Why is a jQuery plugin necessary?Chuvash

© 2022 - 2024 — McMap. All rights reserved.