I have an unusual requirement. Essentially I need a way so that, when the user clicks on a link or button, they will receive a PDF. The tricky part here is that the server won't process the request at all unless a custom header is sent with it (otherwise it deems the person logged out and sends them to the login screen).
At the moment the way the header works cannot be changed so please don't dwell on it; it will get changed in the future and is an internal application that I have no control over.
The options I have explored:
- Using an iframe or simply opening a new window with some sort of path that will return the PDF. This can't work because I cannot specify the required header for the PDF and would be redirected before reaching the PDF itself.
- Using a form and submitting the request can't work because I can't add any custom headers to forms (only XHR and plugins can, AFAIK).
- Using XHR can't work because, while it can add the header and retrieve the file, there is no way to save it on the client side.
It would appear my only options at this point are essentially:
- Use some sort of plugin such as Flash or Silverlight to request the file.
- Force the change of the requirement much earlier than expected so that a header is no longer required.
Is there anything I am missing here? I'm hoping someone can either verify my findings or point me to something I missed because, as far as I can tell, there isn't really anything I can do here.
EDIT: This seems apt and confirms what I was thinking: XMLHttpRequest to open PDF in browser
I have an unusual requirement. Essentially I need a way so that, when the user clicks on a link or button, they will receive a PDF. The tricky part here is that the server won't process the request at all unless a custom header is sent with it (otherwise it deems the person logged out and sends them to the login screen).
At the moment the way the header works cannot be changed so please don't dwell on it; it will get changed in the future and is an internal application that I have no control over.
The options I have explored:
- Using an iframe or simply opening a new window with some sort of path that will return the PDF. This can't work because I cannot specify the required header for the PDF and would be redirected before reaching the PDF itself.
- Using a form and submitting the request can't work because I can't add any custom headers to forms (only XHR and plugins can, AFAIK).
- Using XHR can't work because, while it can add the header and retrieve the file, there is no way to save it on the client side.
It would appear my only options at this point are essentially:
- Use some sort of plugin such as Flash or Silverlight to request the file.
- Force the change of the requirement much earlier than expected so that a header is no longer required.
Is there anything I am missing here? I'm hoping someone can either verify my findings or point me to something I missed because, as far as I can tell, there isn't really anything I can do here.
EDIT: This seems apt and confirms what I was thinking: XMLHttpRequest to open PDF in browser
Share Improve this question edited May 23, 2017 at 11:47 CommunityBot 11 silver badge asked May 9, 2012 at 12:47 KrisKris 1,8403 gold badges19 silver badges27 bronze badges 6- 2 How about addding some kind of tunnel between the app and your script? The tunnel could query the app and receive the file, and then set a proper header before flushing the file to the user, thus actually triggering a download. I don't know if this is possible for your system, depending on security. – Johannes Lumpe Commented May 9, 2012 at 12:57
- A tunnel isn't a bad idea though I'm not sure we could implement that here. Hmm. Thanks, I'll look into it. – Kris Commented May 9, 2012 at 13:00
- 1 If you can do without support for IE < 10 (not very likely, right?), you could use XMLHttpRequest Level 2 (XHR2) and Blob URLs. Here's an example: stackoverflow./q/9620497 See also stackoverflow./q/6165266 and html5rocks./en/tutorials/file/xhr2 – David Kolar Commented May 9, 2012 at 13:54
- Actually, we are only support Moz and Webkit so a blob url might work out nicely! I'll take a poke at that. Thanks! – Kris Commented May 9, 2012 at 14:01
- 1 @LasseChristiansen-sw_lasse the only real solution that appears technically possible is using blob URLs. So essentially fetch the PDF blob from a service and passing the headers then embedded the PDF into a blob URL at which point if a user clicks on it they get the PDF. Esailija was pretty similar to my end solution I just never marked it has the answer. – Kris Commented Jul 22, 2014 at 16:35
2 Answers
Reset to default 13Tested to work in chrome:
function toBinaryString(data) {
var ret = [];
var len = data.length;
var byte;
for (var i = 0; i < len; i++) {
byte=( data.charCodeAt(i) & 0xFF )>>> 0;
ret.push( String.fromCharCode(byte) );
}
return ret.join('');
}
var xhr = new XMLHttpRequest;
xhr.open( "GET", "/test.pdf" ); //I had test.pdf this on my local server
xhr.addEventListener( "load", function(){
var data = toBinaryString(this.responseText);
data = "data:application/pdf;base64,"+btoa(data);
document.location = data;
}, false);
xhr.setRequestHeader("magic", "header" );
xhr.overrideMimeType( "application/octet-stream; charset=x-user-defined;" );
xhr.send(null);
You can change application/pdf to application/octet-stream to have download prompt. But it's pretty easy to download from the chrome's reader as well.
In firefox nothing happens I guess it's because I don't have a plugin to deal with application/pdf
installed. Changing to application/octet-stream will prompt a dl.
With IE I suppose you need some kind of VBScript/ActiveX hackery
If the file is huge, using data uri might crash the browser, in that case you can use BlobBuilder and Object URLs.
Instead of linking to the .PDF file, instead do something like
<a href="pdf_server.php?file=pdffilename">Download my eBook</a>
which outputs a custom header, opens the PDF (binary safe) and prints the data to the user's browser, then they can choose to save the PDF despite their browser settings. The pdf_server.php should look like this:
header("Content-Type: application/octet-stream");
$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
EDIT: The only way to add headers to a request from inside a browser (client-side) is use the XmlHttpRequest setRequestHeader method.
xhr.setRequestHeader('custom-header', 'value');