12

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?

guest271314
  • 1
  • 15
  • 104
  • 177
  • 2
    You can check my answer here: https://stackoverflow.com/questions/38524320/download-pdf-file-from-ajax-response/38552959#38552959 It gives exactly what you are looking for. – Dekel Aug 06 '17 at 21:42
  • @Dekel See criteria at OP, `.responseType` was not defined at that point in browser development. – guest271314 Aug 07 '17 at 00:04
  • are you looking for a solution for 2016-browser-compatible or 2017? :) – Dekel Aug 07 '17 at 06:45
  • @Dekel 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?](https://stackoverflow.com/q/38195855/) where posted an Answer that did not meet original criteria, though provided solution, Kaiido accurately pointed out the appropriate context. – guest271314 Aug 07 '17 at 14:07
  • What do you mean without a "server"? – Dehan Aug 09 '17 at 04:17
  • @jdc91 Without requesting the file from a server and without server responding with data having `Content-Disposition` header. Using the browser to offer the download – guest271314 Aug 09 '17 at 04:19
  • What will be the contents of the file. Better if you can state the whole story! Meanwhile, you can try https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL – Dehan Aug 09 '17 at 04:40
  • @jdc91 See _"Better if you can state the whole story!"_ See https://stackoverflow.com/questions/38193605/how-to-updoad-in-old-browsers-ex-safari-5-1-4, https://stackoverflow.com/q/38195855/ – guest271314 Aug 09 '17 at 04:42

6 Answers6

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>
Star
  • 3,222
  • 5
  • 32
  • 48
Leo Farmer
  • 7,730
  • 5
  • 31
  • 47
  • what if user has browser plugin which open mydoc.doc? then how it will be downloaded? – Star Aug 08 '17 at 09:37
  • 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: https://stackoverflow.com/questions/8613725/how-can-i-force-download-with-html-and-or-javascript/8613899#8613899 – Leo Farmer Aug 08 '17 at 19:50
  • `window.open("blob:xyz")` still works well for me in 2023 here's the reference; https://developer.mozilla.org/en-US/docs/Web/API/Window/open – Justin Jun 05 '23 at 16:07
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 :-)

Myst
  • 18,516
  • 2
  • 45
  • 67
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>
Jahid Hasan
  • 224
  • 1
  • 15
2

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.

padr
  • 385
  • 1
  • 4
  • 16
  • Is `File` constructor available at the browsers mentioned at last sentence of Answer? – guest271314 Aug 09 '17 at 13:19
  • No they don't. (http://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. :) – padr Aug 09 '17 at 17:41
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

Star
  • 3,222
  • 5
  • 32
  • 48
guest271314
  • 1
  • 15
  • 104
  • 177
-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);
}