I'm using Polymer Iron Ajax to get a PDF document from the server. However, when forcing a download on the client, Chrome (Version 65.0.3325.181) shows the message "Pop-up blocked" - which is not acceptable from a usability point of view. Any ideas how to get around this so the download is not blocked? I've simplified the code below as the PDF is dynamically generated using Puppeteer from data contained in the ajax request.
Server code using Express.js:
response.type('application/pdf');
response.attachment('resume.pdf');
response.send(mypdf);
app.listen(8080)
Polymer App code:
<iron-ajax id="myironajax" method="GET" handle-as="blob" on-response="handlePdfResponse" url="http://localhost:8080/pdf"></iron-ajax>
handlePdfResponse(e) {
var file = new Blob([e.detail.response], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = 'myfile.pdf';
document.body.appendChild(a);
a.click();
}
Any help greatly appreciated. Thanks.
Related
I have a publicly accessible url to a PDF in Google Cloud Storage. I want to be able to create a button/link in react which allows users to download this PDF to their own computer. I'm wondering what is the best approach to do this and which libraries would be of help? Is there any documentation on this? Thanks
In order to force download a file, you have a number of options. First, the easiest is using the download attribute of an anchor tag:
PDF
However, this is not supported on IE and a number of other browsers in their earlier versions. But the maximum impact of this is it will open in a new tab which in my opinion is graceful degradation. See the full list of supported versions.
If this is not enough, you have to make some changes server-side. You can configure a server in many ways, but as an example, a .htaccess file can have the following:
<Files *.pdf>
Header set Content-Disposition attachment
</Files>
You can dynamically generate a link or button. Snippet bellow:
var sampleBytes = new Int8Array(4096); // In your case it should be your file
var saveByteArray = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, name) {
var blob = new Blob(data, {type: "octet/stream"}), // or application/pdf
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = name;
a.click();
window.URL.revokeObjectURL(url);
};
}());
saveByteArray([sampleBytes], 'example.txt'); // You can define the filename
I want to download pdf file directly without viewing, i have tries following things till now but nothing is helping.
1- window.open("https://s3-link1.pdf", 'Download');
2- <a href="https://s3-link1.pdf" download>Link</a>
Link - https://s3-link1.pdf
Assume my domain is https://www.somedomain.com
I somewhere read we can't download cross-origin files. content-disposition header is required to be passed from backend. I am puzzled here. Another csv file of cross-origin is being downloaded easily.
https://s3-link2.csv
I just need to download pdf file using javascript. Please guide me.
Try with fetch.
fetch("https://s3-link1.pdf", {
method: 'GET'
}).then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = "name"; // the filename you want
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
Option 1:
with jQuery you can try this:
$.get("https://s3-link1.pdf", function (result)
{
var blob = new Blob([result]);
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "myFileName.pdf";
link.click();
});
Option 2:
The download attribute works in all modern browsers, including MS Edge, but not Internet Explorer.
In the latest versions of Chrome, you cannot download cross-origin files (they have to be hosted on the same domain).
<a href="https://s3-link1.pdf" download>Download PDF</a>
Find more about it here on this blog: https://actualwizard.com/html-force-download-file
I have a protected API that fetches the contents of a file. By protected I mean, I need to send in Authorization headers before the API will allow me to fetch the file contents.
How do I display this in a browser window?
Currently, my nodejs backend is returning the contents with Content-Type:text/html
On the frontend, my current code looks like this
$http.get(downloadUrl)
.then(function(resp) {
var data = resp.data;
var blob = new Blob([data], { type: "text/html" });
let objectUrl = (window.URL || window.webkitURL).createObjectURL( blob );
let anchor = document.createElement("a");
anchor.href = objectUrl;
anchor.download = 'source.html';
anchor.click();
window.URL.revokeObjectURL(objectUrl);
This just download the file though. I just want to display it, preferably in a new window.
Edit I believe this is a duplicate of this question and there is no front-end-only solution to it. It requires the backend to play a part, such as implementing a "Holder-Of-Key Authentication Scheme"
I'm working with an existing Electron project (convert web app to desktop app), which has a task that is to export content on screen to pdf/png/jpg.
Here is the situation:
The desktop app is purely client-side code, it doesn't connect to any API or server (just in case you suggest a solution using Nodejs server-side code)
I got the dataUrl from canvas object already (it's a base64 string of the file)
How can I save that dataUrl into a file (pdf/png/jpg)?
Here are some ways that I tried:
The good old window.location = dataUrl (nothing happens)
Create a form inside the div, action = dataUrl, then submit the form
Both ways are not working!
Thank you very much
For the download to occur the MIME type of the data URI needs to be changed to "application/octet-stream"
var dataURL = "data:text/plain,123";
var form = document.createElement("form");
form.action = dataURL.replace(/:[\w-/]+(?=,)/, ":application/octet-stream");
form.method = "GET";
document.body.appendChild(form);
form.submit();
Using <a> element with download attribute
var dataURL = "data:text/plain,123";
var a = document.createElement("a");
a.download = "file";
a.href = dataURL;
document.body.appendChild(a);
a.click();
See also How to download a file without using <a> element with download attribute or a server??
I need help. I have an angular app and by using DocRaptor want to generate PDF and save it as file. But I cant trigger the dialog to save file in Safari with any method what I have found on Stack Overflow. Those methods open file in current browser tab and replace site html or open file in new tab. No one cant shows the dialog. Here the examples what I have already tried to use. Environment MacOS - EL Capitan. Safari 9.0.3
Solution #1
var content = 'file content for example';
var blob = new Blob([ content ], { type : 'text/plain' });
$scope.url = (window.URL || window.webkitURL).createObjectURL( blob );
Example jsfiddle. Shows file in current tab. Replaces site. But works in Chrome.
Solution #2
<a target="_self" href="mysite.com/uploads/ahlem.pdf" download="foo.pdf">
Example jsfiddle. Doesnt work at all in Safari. Works in Chrome.
Solution #3
<a class="btn" ng-click="saveJSON()" ng-href="{{ url }}">Export to JSON</a>
and
$scope.saveJSON = function () {
$scope.toJSON = '';
$scope.toJSON = angular.toJson($scope.data);
var blob = new Blob([$scope.toJSON], { type:"application/json;charset=utf-8;" });
var downloadLink = angular.element('<a></a>');
downloadLink.attr('href',window.URL.createObjectURL(blob));
downloadLink.attr('download', 'fileName.json');
downloadLink[0].click();
};
Example Code Snippet. Shows the file content instead of document's html.
Solution #4
function download(text, name, type) {
var a = document.getElementById("a");
var file = new Blob([text], {type: type});
a.href = URL.createObjectURL(file);
a.download = name;
}
Example Code Snippet. Replace document with file content in Safari. Works in Chrome.
And similar Solution #5
function download(text, name, type) {
var a = document.createElement("a");
var file = new Blob([text], {type: type});
a.href = URL.createObjectURL(file);
a.download = name;
a.click();
}
Example jsfiddle. Doesnt work at all in Safari. Works in Chrome.
Also I have tried to use libraries like:
FileSaver - It opens file in Safari instead of document. So you should click Cmd+S. Example.
If we use type 'pplication/octet-stream' the name of file will be unknown or there was be an error 'Failed to load resource: Frame load interrupted'. Issue.
Second library Downloadify - doesnt work in Safari at all. Issue.
Angular library nw-fileDialog - instead of save as it shows choose file. Issue.
DocRaptor has own example with jQuery.
Example with angular in jsfiddle. It works in Chrome but in Safari example doesnt work be cause of error with SAMEORIGIN
Refused to display 'https://docraptor.com/docs' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.
But if we reproduce it on server and change url on 'https://docraptor.com/docs.pdf' it works and open file in new tab and automatically download the file so you cant choose a folder and after download user see white empty screen tab in browser. If we specify form target="_self" it will work perfect, but console will have an error 'Failed to load resource:'.
I will appreciate any help with this problem.
Thanks.
Regards.
Try using Blob file for this:
// Buffer can be response from XMLHttpRequest/Ajax or your custom Int32 data
function download(buffer, filename) {
var file = new Blob([buffer], {
type: 'application/octet-stream' // Replace your mimeType if known
});
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
var converted = e.target.result;
converted.name = filename;
converted.webkitRelativePath = filename;
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.src = converted;
};
fileReader.onerror = function(e) {
throw new Error('Something is wrong with buffer data');
};
fileReader.file = file;
fileReader.readAsDataURL(file);
}
It basically uses filebuffer and download that as an iframe content. Make sure to hook correct mime type so that safari security system will recieved analyse filetype.
Ideally, Solution #2 would be the answer, but the download attribute does not yet have cross-browser support.
So you have to use a <form> to create the download. As you noted, DocRaptor's jQuery example uses this technique.
The SAMEORIGIN error is actually because JSFiddle is running the code in an iFrame with their origin settings. If you run this straight from your Angular application, you shouldn't have any problems.