How to Use Content-disposition for force a file to download to the hard drive?

HtmlDownloadHttpresponseContent Disposition

Html Problem Overview


I want to force the browser to download a pdf file.

I am using the following code :

<a href="../doc/quot.pdf" target=_blank>Click here to Download quotation</a>

It makes the browser open the pdf in a new window, but I want it to download to the hard drive when a user clicks it.

I found that Content-disposition is used for this, but how do I use it in my case?

Html Solutions


Solution 1 - Html

On the HTTP Response where you are returning the PDF file, ensure the content disposition header looks like:

Content-Disposition: attachment; filename=quot.pdf;

See content-disposition on the wikipedia MIME page.

Solution 2 - Html

With recent browsers you can use the HTML5 download attribute as well:

<a download="quot.pdf" href="../doc/quot.pdf">Click here to Download quotation</a>

It is supported by most of the recent browsers except MSIE11. You can use a polyfill, something like this (note that this is for data uri only, but it is a good start):

(function (){

	addEvent(window, "load", function (){
		if (isInternetExplorer())
			polyfillDataUriDownload();
	});

	function polyfillDataUriDownload(){
		var links = document.querySelectorAll('a[download], area[download]');
		for (var index = 0, length = links.length; index<length; ++index) {
			(function (link){
				var dataUri = link.getAttribute("href");
				var fileName = link.getAttribute("download");
				if (dataUri.slice(0,5) != "data:")
					throw new Error("The XHR part is not implemented here.");
				addEvent(link, "click", function (event){
					cancelEvent(event);
					try {
						var dataBlob = dataUriToBlob(dataUri);
						forceBlobDownload(dataBlob, fileName);
					} catch (e) {
						alert(e)
					}
				});
			})(links[index]);
		}
	}

	function forceBlobDownload(dataBlob, fileName){
		window.navigator.msSaveBlob(dataBlob, fileName);
	}

	function dataUriToBlob(dataUri) {
		if  (!(/base64/).test(dataUri))
			throw new Error("Supports only base64 encoding.");
		var parts = dataUri.split(/[:;,]/),
			type = parts[1],
			binData = atob(parts.pop()),
			mx = binData.length,
			uiArr = new Uint8Array(mx);
		for(var i = 0; i<mx; ++i)
			uiArr[i] = binData.charCodeAt(i);
		return new Blob([uiArr], {type: type});
	}

	function addEvent(subject, type, listener){
		if (window.addEventListener)
			subject.addEventListener(type, listener, false);
		else if (window.attachEvent)
			subject.attachEvent("on" + type, listener);
	}

	function cancelEvent(event){
		if (event.preventDefault)
			event.preventDefault();
		else
			event.returnValue = false;
	}

	function isInternetExplorer(){
		return /*@cc_on!@*/false || !!document.documentMode;
	}
	
})();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKrishView Question on Stackoverflow
Solution 1 - HtmlOdedView Answer on Stackoverflow
Solution 2 - Htmlinf3rnoView Answer on Stackoverflow