Download PDF in browser with blob - javascript

I can not quite wrap my head around on how to download a PDF from a google spreadsheet PDF Export Weblink. I generated a testing spreadsheet for this case.
I understand that I need to implement encodeURIComponent and/or "Buffer.from" to the blob but however I do it, it only downloads a broken PDF for me.
This is what I currently have in its rawest form. Thank you for your support!
Node JS:
const fetch = require('node-fetch');
var url = "https://docs.google.com/spreadsheets/d/1fLjKASR_g5wsvOjjJi6RclqMVd2o_1On-OfimXtId4E/export?exportFormat=pdf&format=pdf&size=A4&fzr=true&gid=477517973&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&portrait=true&fitw=true&fith=true&top_margin=0.20&bottom_margin=0.20&left_margin=0.20&right_margin=0.20";
let blob = await fetch(url).then(r => r.blob());
// then send blob variable to javascript
Javascript:
function downloadURI(name) {
var uri = 'data:application/pdf;base64,' + blob;
var link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
downloadURI("test"+".pdf")

I thought that from var uri = 'data:application/pdf;base64,' + blob; in your script, in this case, it is required to convert the downloaded data as the base64. Although I'm not sure about the relationship between the scripts between Node JS: and Javascript:, in your situation, how about the following modification?
From:
let blob = await fetch(url).then(r => r.blob());
To:
let buf = await fetch(url).then((r) => r.arrayBuffer());
const data = Buffer.from(buf).toString("base64");
By this, you can use data as follows.
var uri = 'data:application/pdf;base64,' + data;
Note:
As the additional information, for example, if you want to download your Spreadsheet as a PDF file using only Javascript, you can also use the following script. But, in this case, the Spreadsheet is required to be publicly shared. Please be careful about this.
async function downloadURI(name) {
var url = "https://docs.google.com/spreadsheets/d/1fLjKASR_g5wsvOjjJi6RclqMVd2o_1On-OfimXtId4E/export?exportFormat=pdf&format=pdf&size=A4&fzr=true&gid=477517973&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&portrait=true&fitw=true&fith=true&top_margin=0.20&bottom_margin=0.20&left_margin=0.20&right_margin=0.20";
let blob = await fetch(url).then((r) => r.blob());
var f = new FileReader();
f.readAsDataURL(blob);
f.onload = d => {
var uri = d.target.result;
var link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
}
downloadURI("test"+".pdf")

Related

How to unzip and download all images from zip folder using javascript?

I have tried using jszip and able to extract only 10 images from the zip file.But ZIp file contains 450 images.
By using the below code I am able to download 10 images only. Not extracting all images of zip folder.
function unzipfeb146() {
var i = 0;
// fetch('file:///C:/CBTOffline/Images/8687.Zip')
fetch('http://localIP/CBT/R3Images/QBQuestionImages/8688.zip')
.then(response => response.arrayBuffer())
.then(data => {
// Extract the files from the zip
const zip = new JSZip();
return zip.loadAsync(data);
})
.then(zip => {
// Download each file
Object.keys(zip.files).forEach(filename => {
debugger;
zip.files[filename].async('blob').then(blob => {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
`your text`
link.download = filename;
document.body.appendChild(link);
link.click();
var img = document.createElement("img");
img.src = URL.createObjectURL(blob);
img.id = i + 1;
document.body.appendChild(img);
i = i + 1;
//const image = new Image();
//image.src = URL.createObjectURL(blob);
//image.id = fileName;
//document.body.appendChild(image);
//document.body.removeChild(link);
});
});
})
.catch(error => console.error(error));
}
Expected out put as below :
To create a download link for a zipped file, you can use the tag with the href attribute pointing to the location of the zipped file, like this:
Download file

JS download doesn't download entire file

I am trying to download a csv file with 3607 lines (1.0 Mb):
const hiddenElement = document.createElement('a');
const fileContent = `data:text/csv;charset=ansi,${res.data}`;
hiddenElement.href = fileContent;
hiddenElement.target = '_blank';
hiddenElement.download = 'file.csv';
hiddenElement.click();
The content at res.data is complete (as well as fileContent), but when i download the csv, the file only has 149 lines (4.4 Kb) instead of the original size.
Can someone help me please?
The problem was that URLs cant have more than 2,048 characters
I faced the same problem and the same CSV download used to work earlier and download complete file.
had to change to the following:
const blob = new Blob([csvData], { type: 'text/csv' })
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a')
link.setAttribute('href', url)

CSV file from server URL not downloading

I'm messing with a piece of code to download a CSV from server. this is what I'm trying:
downloadCSVTemp(){
let name = 'report.csv';
const response = api.getReportCSV()
.then((res)=>{
const blob = new Blob([res], { type: "data:text/csv;charset=utf-8," });
const blobURL = window.URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.download = name;
anchor.href = blobURL;
anchor.dataset.downloadurl = ["text/csv", anchor.download, anchor.href].join(
":"
);
anchor.click();
});
}
getReportCSV(){
return axios.get("/export/assessments/");
}
I intend to download a csv file from server url by an axios call, But this code is downloading an csv file which can't be opend by the browser & full of garbage data. What's the problem here ?
The res argument contains Axios response object. When creating the blob, you should use res.data:
new Blob([res.data], { type: "data:text/csv;charset=utf-8," });

how to get mime type from content-type

The thing is axios calls return files. sometimes xlsx, sometimes plain txt.
In javascript, as soon as I get them, i force download it via blob.
Something like this:
var headers = response.headers;
var blob = new Blob([response.data], {
type: headers['content-type']
});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "report.xlsx";
link.click();
As you see, I got something like this: link.download = "report.xlsx" . What I want is to replace xlsx with dynamic mime type so that sometimes it's report.txt and sometimes it's report.xlsx.
How do I do that from content-type?
You can get the file extension using the content type of headers.
Use this Javascript library - node-mime
You just want to pass your headers['content-type'], it will give you the file extension which you need to set for download name.
var ctype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
console.log(mime.getExtension(ctype));
<script src="https://wzrd.in/standalone/mime#latest"></script>
Example: In your case,
var headers = response.headers;
var blob = new Blob([response.data], {
type: headers['content-type']
});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "report." + mime.getExtension(headers['content-type']);
link.click();
Incomplete list of MIME types from Mozilla Developers.
What is the backend of your application? I used this in C# (.NET Core) to get the content type of a file then set it as a header in the response:
public string GetContentType (string filePath) {
var contentTypeProvider = new FileExtensionContentTypeProvider();
string contentType;
if( !contentTypeProvider.TryGetContentType( filePath, out contentType ) ) {
contentType = "application/octet-stream";
};
return contentType;
}
Edit: modified OP code to handle content type dynamically:
var headers = response.headers;
var responseType = headers['content-type'];
var fileType = "text/plain";
var fileName = "report.txt";
if ( responseType == "application/octet-stream" ) {
fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
fileName = "report.xlsx";
}
var blob = new Blob([response.data], {
type: fileType
});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();

Save json string to client pc (using HTML5 API)

I read few older thread about the same, but seen the file API changed a lot recently. My requirement is to save a json file (data is locally in indexdDB, but I need a way to back it up). Since I use indexdDB, I only target recent browsers, mainly chrome. So, it it possible to save data (json string) to client computer?
I have seen http://eligrey.com/demos/FileSaver.js/ , but is there a way to do it natively?
Thanks.
You can use a Blob and the HTML5 a[download] feature to provide a JSON backup download:
var data = {a:1, b:2, c:3};
var json = JSON.stringify(data);
var blob = new Blob([json], {type: "application/json"});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = "backup.json";
a.href = url;
a.textContent = "Download backup.json";
Here is a jsfiddle example: http://jsfiddle.net/potatosalad/yuM2N/
Yes, you can. This assumes that you have the json in text:
var toDownload=new Blob([text],{type:'x-whatever/x-backup'});
var link=window.URL.createObjectURL(toDownload);
window.location=link;
that is untested, but it should work.
You can use FileSaver.js.
Sample code:
//include the js file in html.
<script src="FileSaver.min.js"></script>
// other code ...
//use it here.
var myjson= "{a:3, b:4}";
var blob = new Blob([myjson], {type: "application/json"});
var saveAs = window.saveAs;
saveAs(blob, "my_outfile.json");
Use JSON.stringify to create a string from JSON.
Fiddle: https://jsfiddle.net/9w9ofec4/3/
based on potatosalad answer i experimented with an 'self' updating link:
jsfiddle
function saveAsFile(link, content, filename) {
var blob = new Blob([content], {type: "text/text"});
var url = URL.createObjectURL(blob);
// update link to new 'url'
link.download = filename + ".txt";
link.href = url;
}
saveAsFile(this, "YourContent", "HelloWorldFile");
the function saveAsFile() needs the calling a element as first argument.
than it updates the href target to the new blob.
function saveAsJSON(data, name=Date.now()+'.json') {
const a = document.createElement('a')
a.download = name
a.href = URL.createObjectURL(new Blob([JSON.stringify(data)], {type: 'application/json'}))
a.click()
}
// https://stackoverflow.com/questions/62371219/chrome-stops-download-files-from-stackoverflow-snippets
saveAsJSON(['orange', 'banana', {name: 'apple'}])
To save the file with a custom name, you can create a hidden <a> element and then click on it. This method is used by FileSaver.js.
function download(name, text){
var toDownload=new Blob([text],
{type:'data:application/octet-stream'});
var link = window.URL.createObjectURL(toDownload);
var el = document.createElement("a");
el.href = link;
el.download = name;
el.click();
window.URL.revokeObjectURL(link);
}

Categories