16

I want to host on my webpage an external url containing a mp3 file. The problem is that clicking on that link will open the player, i have to right click and "Save link as" in order to download the file. Is there any solution to force the file download?

I don't want to download the file and then use headers to force the download.

Dmitry Pashkevich
  • 13,431
  • 9
  • 55
  • 73
keepwalking
  • 2,644
  • 6
  • 28
  • 63

3 Answers3

19

Now the HTML5 spec defines a very useful download attribute on hyperlinks that basically allows to force download behavior on client-side, regardless of what comes in Content-Type and Content-Disposition from the server:

In some cases, resources are intended for later use rather than immediate viewing. To indicate that a resource is intended to be downloaded for use later, rather than immediately used, the download attribute can be specified on the a or area element that creates the hyperlink to that resource.

<...>

The download attribute, if present, indicates that the author intends the hyperlink to be used for downloading a resource. The attribute may have a value; the value, if any, specifies the default filename that the author recommends for use in labeling the resource in a local file system.

So all you need to do is add the attribute to your hyperlink and the browsers that support it would understand that the content needs to be downloaded:

<a href="http://example.com/media.mp3" download>Download Your File</a>

You can even suggest a different name for the downloaded file by setting the attribute value:

<a href="http://example.com/media.mp3" download="check this out.mp3">Download Your File</a>

More info and demos:

Browser support: caniuse.com


Downloading generated content

You can even make a link that will download a content that you generated, as long as there is a way to get a base64-encoded data URI for it:

<a href="data:application/octet-stream;base64,YOUR_ENCODED_DATA" download="song.mp3">Download</a>

For more details on saving generated content, refer to this article by Eli Grey:

Saving generated files on the client-side

Dmitry Pashkevich
  • 13,431
  • 9
  • 55
  • 73
  • What if mp3 is generated after page load by user? If you create a 'fake' anchor tag and jquery 'click' it, it doesn't work ... How would I accomplish the same and force download with JS ? probably not possible? – trainoasis Dec 03 '14 at 10:48
  • @trainoasis You can generate a link if you can get a Data URI for your generated mp3 (which I believe you can). See my updated answer – Dmitry Pashkevich Dec 07 '14 at 01:46
  • 7
    Note this only works for same-origin URLs: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a – Crashalot Sep 21 '19 at 23:58
  • 1
    @Crashalot is there a way to do this with cross-origin URLs? – krummens Aug 15 '22 at 19:19
  • You can convert any external image url to base64 and then set it as the href attribute with javascript – Brentspine Dec 30 '22 at 21:44
3

EDIT: The answer below applies if you have control over the target MP3 file only, not if it is an external link

The link should not go directly to the MP3 file, but to a piece of logic (are you using ASPX, for instance? In that case you can use an .aspx page as the target, or you can create an HTTP handler for the .mp3 extension) that adds an HTTP header to the output that contains the line:

Content-Disposition: attachment;filename="whatever.mp3";

This will instruct the browser to treat the contents of the output as a file to save locally.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
1

This worked for me using JavaScript

<a onclick="saveFile('url')">Download</a>

<script>
    function saveFile(url) {
    // Get file name from url.
    var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
    var xhr = new XMLHttpRequest();
    xhr.responseType = 'blob';
    xhr.onload = function() {
        var a = document.createElement('a');
        a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
        a.download = filename; // Set the file name.
        a.style.display = 'none';
        document.body.appendChild(a);
        a.click();
        delete a;
    };
    xhr.open('GET', url);
    xhr.send();
    }
</script>

clicking on <a> tag will download your file directly

Bruno
  • 655
  • 8
  • 18