Print file on client side - javascript

I am using FileSaver.js to print an object array on the client side (HTML/Typescript).
var blob = new Blob([JSON.stringify( marray)], {type: "text/plain;charset=utf-8"});
saveAs(blob, "Data.txt");
It works fine. The problem is it downloads in the download folder (by default). I want to add a file path along with its name. Any idea? Or another way to do this job. fs is not working in this case. it is not recognizing fs and gives the error fs.writefilesync is not a function

How do you know what path the user has?
It is not safe. There is no way to "climb" the user's file system
If you open the source code, you will see the simplest implementation scheme there. It's just a click on a link download
var a = document.createElement('a')
// ...
a.href = blob
// ...
a.dispatchEvent(new MouseEvent('click'))

Related

Why my ZIP file from NodeJS server is not readable?

I'm making a web service that will return some generated zip files to a client.
Currently I did a really simple code for my test and when I query directly this service the ZIP file is well returned. In a near future, I'll need to pass some parameters through the header and so a simple link on the client side will not do the job.
So I decided to use XmlHttpRequest on my client to query the resource and download it as a simple file. The problem comes here, when I generate the download with the server response, the zip file doesn't work.
Here is the NodeJS code (with express) :
.get('/myservice', function(req, res)
{
res.setHeader('Content-Type', 'application/zip');
const JSZip = require('jszip');
const zip = new JSZip();
zip.file('hello.txt', 'Hello world\n');
zip
.generateAsync({type: 'nodebuffer'})
.then(function(content)
{
res.send(content)
}.bind(res));
}
Here is the client side Javascript that call the service and then make a file from the answer :
var req = new XMLHttpRequest();
req.open("GET", "https://mydomain/myservice", false);
req.send(null);
function download(filename, text)
{
var element = document.createElement('a');
element.setAttribute('href', 'data:application/zip;charset=base64,' + text);
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
console.log(req.responseText)
download('test.zip', req.responseText);
I think that I completely miss understand the encoding on the client, but I didn't find the solution.
The downloaded file, when unzip, give me a file that contain the same zip that also do the same thing.
When I call the service with XmlHttpRequest, it is well called and does not throw any error.
I'm using JSZip to generate the zip.
I precise that I can't use blob on generateAsync from JSZip because that throw me an error.
Any solution ?
You dont need to make it so complicated. As you are piping a file already. Just use window.open('/myservice'); as the browser will handle the fact its a file and keep the current page open and download the file.
https://codesandbox.io/s/hardcore-euclid-9nkft

Is there a way to download any kind of file using angular filesaver?

I'm using node.js and angular.js for my app and I'm trying to download files through the browser using Blob and fileSaver.js.
I've used these in other sections of my app to download text files and pdf files specifying the correct type when creating the Blob object without any problem, but in the current section I need to support any type of file and I don't know if it's possible.
For example, I've tried downloading an image file with and without type:image/png and the result was a corrupted image - inspecting it in a text editor and comparing it with the original file shows that many of the bytes were changed.
Here are the code snippets I use:
Server:
fs.readFile(/* snipped file path */, function(err, data){
if(err){
/* handle error */
}
else{
res.send(data);
}
});
Client:
$http.get(/* endPoint URL */)
.success(function(result){
var data = new Blob([result], {type: 'image/png'});
FileSaver.saveAs(data, filename);
});
A few questions:
Do I need to specify type for Blob? If so, do I need to specify it at server, too (it's a pain to determine it)? Can't I just skip it on both ends?
What causes the image test to result in corrupted file? Am I missing some content-type header or something?
Try adding {contentType: 'arraybuffer'} to your GET request and remove type from Blob definition, like so:
$http.get(/* endPoint URL */, {contentType: 'arraybuffer'})
.success(function(result){
var data = new Blob([result]);
FileSaver.saveAs(data, filename);
});
(Edit: deleted redundant type definition from Blob)

Download a file from a server with JavaScript / Typescript

I have a problem when I try to download a file stored on a server. I make a call and get a right response in which I have all the information I need, in the headers I have the content type and the file name, and I have the file body in the response body.
What I want to do is to simply make a download process, so I tried to do so, data being the http call response :
// Get headers info
let headers = data.headers
let contentType = headers.get("Content-Type")
let name = headers.get("name")
// Initialize Blob
let blob = new Blob([data.text()], {type: contentType})
// Make the download process
let a = window.document.createElement("a")
a.href = window.URL.createObjectURL(blob)
a.download = name
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
For a text file, it's working as it's an easy format, but for like a picture or a PDF file it makes download a file of the right name and type, but they can't be well read.
Has anyone an idea ? Thanks !
Found a way to do it using the way described below by simulating an tag with href and download parameters :)
how to set a file name using window.open

Using ExcelBuilder.js with FileSaver.js

In my application I cant use Downloadify (which is recommended by ExcelBuilder.js) so I tried to download my .xlsx file with FileSaver.js
I tried both
var blob = new Blob([builder.createFile(basicReport.prepare())],{
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base65"
})
saveAs(blob, "myXLSX.xlsx");
and
var blob = new Blob([builder.createFile(basicReport.prepare())],{
type: "application/vnd.ms-excel;charset=charset=utf-8"
})
saveAs(blob, "myXLSX.xlsx");
I can download the file and i tried .xls and .xlsx extensions as well. The Excel cant open the .xlsx and if i try to open the .xls it opens but the data is uninterpretable.
Update 14-Sep-2017: there is a simpler code for this as you can see at https://github.com/eligrey/FileSaver.js/issues/262#issuecomment-256602092. You can remove the new Blob line and just use:
ExcelBuilder.Builder.createFile(workbook, {type:'blob'})
.then(function(blob) {
FileSaver.saveAs(blob, 'File.xlsx');
});
I was having the same issue today, but with the Angular version of FileSaver.js. And I solved it unintentionally. The following code just worked:
ExcelBuilder.Builder.createFile(workbook, {type:'blob'})
.then(function(blob) {
var data = new Blob([blob], {type:'base64'});
FileSaver.saveAs(data, 'File.xlsx');
});
My libraries "angular-file-saver": "1.1.2" and "excel-builder-js": "https://github.com/rodrigosaling/excel-builder.js.git#master" that is a fork of excel-builder.js#2.0.2.
Some clarifications (because it was not 100% unintentional):
the {type:'blob'} came from
https://github.com/stephenliberty/excel-builder.js/issues/4#issuecomment-54961321;
the createFile() returns a promise and not a file (without the then() the library will create a file containing a "Promise" text on the first cell);
my fork of the library is to replace the generate() by generateAsync() on JSZip library. generate() was replaced on v3 that is the version ExcelBuilder requests;
why the {type:'base64'}? It's only a guess, but I think is what an Excel file is after its content is zipped. I don't know.
I couldnt make it with fileSaver.js library so I made a link in my event handler, clicked it and then removed the link.
var myA = document.createElement('a');
myA.setAttribute('href', "'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' + EB.createFile(workbook));
myA.setAttribute('download', "myXLSX.xlsx");
document.getElementById("mydiv").appendChild(myA);
myA.click();
document.getElementById("mydiv").removeChild(myA);

encodeURI file download - crashing browser

I created a web application to clean up CSV/TSV data. The app allows me to upload a CSV file, read it, fix data, and then download a new CSV file with the correct data. One challenge I have run into is downloading files with more than ~ 2500 lines. The browser crashes with the following error message:
"Aw, Snap! Something went wrong while displaying this webpage..."
To work around this I have changed the programming to download multiple CSV files not exceeding 2500 lines until all the data is downloaded. I would then put together the downloaded CSV files into a final file. That's not the solution I am looking for. Working with files of well over 100,000 lines, I need to download all contents in 1 file, and not 40. I also need a front-end solution.
Following is the code for downloading the CSV file. I am creating a hidden link, encoding the contents of data array (each element has 1000 lines) and creating the path for the hidden link. I then trigger a click on the link to start the download.
var startDownload = function (data){
var hiddenElement = document.createElement('a');
var path = 'data:attachment/tsv,';
for (i=0;i<data.length;i++){
path += encodeURI(data[i]);
}
hiddenElement.href = path;
hiddenElement.target = '_blank';
hiddenElement.download = 'result.tsv';
hiddenElement.click();
}
In my case the above process works for ~ 2500 lines at a time. If I attempt to download bigger files, the browser crashes. What am I doing wrong, and how can I download bigger files without crashing the browser? The file that is crashing the browser has (12,000 rows by 48 columns)
p.s. I am doing all of this in Google Chrome, which allows for file upload. So the solution should work in Chrome.
I've experienced this problem before and the solution I found was to use Blobs to download the CSV. Essentially, you turn the csv data into a Blob, then use the URL API to create a URL to use in the link, eg:
var blob = new Blob([data], { type: 'text/csv' });
var hiddenElement = document.createElement('a');
hiddenElement.href = window.URL.createObjectURL(blob);
Blobs aren't supported in IE9, but if you just need Chrome support you should be fine.
I also faced same problem. I used this code,it will works fine. You can also try this.
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(new Blob([base64toBlob($.base64.encode(excelFile), 'text/csv')]),'data.csv');
} else {
var link = document.createElement('a');
link.download = 'data.csv';
// If u use chrome u can use webkitURL in place of URL
link.href = window.URL.createObjectURL(new Blob([base64toBlob($.base64.encode(excelFile), 'text/csv')]));
link.click();
}

Categories