Download file in Electron and Angular app - javascript

I have public url to XLSX file.
It is something like:
http://example.com/myfile.xslx
I'm trying to download this file and store it on my PC.
So what I'm doing is making a GET request to http://example.com/myfile.xslx and getting the content of the file and store it in a file.
this.http.get('http://example.com/myfile.xslx', { responseType: 'blob' })
.subscribe((response) => {
console.log(response); // this returns {size: 508079, type: "application/xlsx"}
// here goes the code for writing content into file
});
The problem is I can't get the content of the file.
What I can get is only an object:
{ size: 508079, type: "application/xlsx" }
Any advice is welcome.

How, I solved it:
this.http.get('http://example.com/myfile.xslx', { responseType: 'blob' })
.subscribe((response) => {
console.log(response); // this returns {size: 508079, type: "application/xlsx"}
// here goes the code for writing content into file
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = (data) => {
const csvData = reader.result;
console.log(csvData); // here I get contect of file using file reader
});
So solution was in FileReader().

Whats going on
What your getting is probably a Blob, a Blob has these 2 properties (size and type), however it has some methods to read its contents.
.XSLX files are not text files but binary files, and they can't be easily read like text files.
Possible solutions
If it makes sense in your case you can use .CSV format instead of .XLSX, CSV files are text files and can be read with the blob.text() method.
You can try to read and write to it with a JavaScript-xslx library
like js-xlsx from SheetJS, or something similar.
With js-xlsx it would be something like this:
this.http.get('http://example.com/myfile.xslx', { responseType: 'arraybuffer' })
.subscribe((response) => {
let xslx = XLSX.read(response, {type:"array"});
console.log(xslx);
// here goes the code for writing content into file
})

Related

Convert Excel to PDF programmaticaly

I am using 'exceljs' module in my Angular project to build an Excel file.
Instead of exporting it as Excel file, I would first like to convert it to PDF and then download it as such.
I can successfully export and save this file to my computer:
workbook.xlsx.writeBuffer().then((data) => {
console.log(data); // Uint8Array
console.log(data.buffer); // ArrayBuffer
console.log(new Blob([data])); // Blob
// code I use to export it as an Excel File
const blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'});
const test = FileSaver.saveAs(blob, 'test.xlsx');
});
As written above, instead of an Excel file I would like to have it exported as a PDF file.
From the code you can see that 'exceljs' is giving me an Uint8Array stream of data, from which I can get out an ArrayBuffer, or I can convert it to a Blob.
I have tried using this without success:
workbook.xlsx.writeBuffer().then((data) => {
const blob = new Blob([data], { type: 'application/pdf' });
// or with 'application/octet-stream' type
// const blob = new Blob([data], { type: 'application/octet-stream' });
FileSaver.saveAs(blob, 'test.pdf');
});`
The PDF file gets exported, but it cannot be opened.
I get an error like "The file is corrupted."
Thank you for all the help in advanced.

FileReader.readAsDataURL() reader result is empty for font files such as .ttf, .woff, and .woff2

I am building a web interface that allows the user to upload a custom font. The problem is that I am unable to convert the font files (specifically, .ttf, .woff, and .woff2 files) to base64 via the FileReader.readAsDataUrl() so that I can then PUT these files via my API.
I can successfully reasAsDataUrl .png and .jpg files, and receive those files' data as a base64 encoded strings, no problem. However, when I try to do the same thing with a .ttf, .woff, or .woff2 file, reader.result is empty although the FileReader doesn't throw any error.
I am using input elements to allow the user to select a font:
<input type="file" accept="application/font-woff" onChange={handleUpload}/>
The handleUpload function looks like this:
handleUpload: () => (event: Object) => {
const { currentTarget: element } = event;
if (!element.files) { return; }
const file = element.files[0];
const reader = new FileReader();
reader.onerror = (error) => {
console.error('Error: ', error);
};
reader.readAsDataURL(file);
console.log(reader.result); // reader.result is empty
}
This is the file object that I am passing to the readAsDataURL function.
I figured it out :-)
readAsDataURL was working successfully but I was returning reader.result before the read was complete. I changed my code to include
reader.addEventListener('load', () => {
change(name, reader.result);
}, false);
and now it's working!
Additional info (edit): The reason why it was working for the image files was because in the onUpload function for those input components I was rendering a preview image which depended on the file being done loading... as a side effect of waiting for the file in order to render the preview, I was also ensuring that the file was loaded before I did anything with it afterwards. I was happy to realize this because if one day, for some reason, I removed the image preview piece, my image upload would have also broken!

How to replace contents of file in a zip using JSzip?

I have been working on a project, I download a zip file from internet through XMLHttpRequest (type: blob ) and then I try to read its content using JSzip.So every zip has a json which I am interested in say manifest.json. So I was successful to read it with this code.
var read_zip = new JSZip();
res=xhr.response;
read_zip.loadAsync(xhr.response).then(function (zip) {
return zip.file("manifest.json").async("string");
}).then(function (text) {
obj = JSON.parse(text);
console.log(text);});
after this I made some changes to 'obj', Now I want to replace the existing manifest with this modified 'obj' json contents and save it.
I was trying this code
var write_zip = new JSZip();
write_zip.loadAsync(xhr.response).then(function (zip) {
zip.file("manifest.json" , obj) ;
zip.generateAsync({type:"blob"})
.then(function (blob) {
saveAs(blob, "hello.zip");
});});
but I am getting this error
Uncaught (in promise) Error: Can't read the data of 'manifest.json'.
Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc)
?
sorry, I am new to this.
It looks like you're trying to write an object into zip which is not supported. According to the documentation on JsZip the value to be written needs to be of type:
String/ArrayBuffer/Uint8Array/Buffer/Blob/Promise/Nodejs stream
See: JSZip#file(name, data [,options])

Javascript Blob anchortag download produces corrupted file

the following code downloads a file that can't be opened(corrupt) and I have absolutely no idea why. I've tried this in so many ways but it never works, it always produces a corrupt file. The original file isn't the problem because it opens fine. I'm trying to open mp4, mp3, and image files.
//$scope.fileContents is a string
$scope.fileContents = $scope.fileContents.join(",");
var blob = new Blob([$scope.fileContents], {type: $scope.file.fileDetails.type});
var dlURL = window.URL.createObjectURL(blob);
document.getElementById("downloadFile").href = dlURL;
document.getElementById("downloadFile").download = $scope.file.fileDetails.name;
document.getElementById("downloadFile").click();
window.URL.revokeObjectURL(dlURL);
You need to download the file contents as binary using an ArrayBuffer e.g.
$http.get(yourFileUrl, { responseType: 'arraybuffer' })
.then(function (response) {
var blob = new Blob([response.data], {type: $scope.file.fileDetails.type});
// etc...
});
Sources:
angular solution
plain javascript solution

Append image file to form data - Cordova/Angular

I am using Anuglar, Ionic and Cordova in my current project, and I'm trying to POST FormData containing an image file to my server. Right now I'm using the cordova camera plugin to return a file path to the image on the device (ex: file://path/to/img). Once I have the file path I want to append the image file to a FormData object using the images file path. Here is my code right now.
var fd = new FormData();
fd.append('attachment', file);
fd.append('uuid', uuid);
fd.append('userRoleId', userRole);
The code above works when appending a file that is taken from an <input type='file'> but doesn't work when just given the file path on the device.
Basically the FormData is showing like this right now:
------WebKitFormBoundaryasdf
Content-Disposition: form-data; name="attachment";
file://path/to/img
and I want it to look like this
------WebKitFormBoundaryasdf
Content-Disposition: form-data; name="attachment"; filename="jesus-quintana.jpg"
Content-Type: image/jpeg
I found many different ways to upload the image using cordova FileTransfer and by converting the image to a base64 and then uploading it. But I couldn't find any simple ways of just grabbing the file by using the path and posting it within a form. I'm not very familiar with the File Api so any help would be appreciated
After some fiddling around I manage to figure out a pretty simple solution.
First I added the cordova file plugin then I use the code below
var fd = new FormData();
window.resolveLocalFileSystemURL(attachment.img, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
var imgBlob = new Blob([ this.result ], { type: "image/jpeg" } );
fd.append('attachment', imgBlob);
fd.append('uuid', attachment.uuid);
fd.append('userRoleId', 12345);
console.log(fd);
//post form call here
};
reader.readAsArrayBuffer(file);
}, function(e){$scope.errorHandler(e)});
}, function(e){$scope.errorHandler(e)});
So I'm just creating a form and using FileReader to insert an ArrayBuffer to the Blob object and then append that to the form data. Hopefully this helps someone else looking for an easy way to do this.
You do need to send file content. With the HTML5 FileAPI you need to create a FileReader object.
Some time ago, I developed an application with cordova and I had to read some files, and I made a library called CoFS (first, by Cordova FileSystem, but it's working in some browsers).
It's on beta state, but I use it and works well. You can try to do some like this:
var errHandler = function (err) {
console.log("Error getting picture.", err);
};
var sendPicture = function (file) {
var fs = new CoFS();
fs.readFile(file, function (err, data) {
if (err) {
return errHandler(err);
}
var fd = new FormData();
fd.append('attachment', new Blob(data));
fd.append('uuid', uuid);
fd.append('userRoleId', userRole);
console.log("Data of file:" + data.toString('base64'));
// Send fd...
});
};
navigator.camera.getPicture(sendPicture, errHandler);
Sorry my poor english.
Your post was extremly helpful to fix my problem. I'm using Ionic 4 and trying to upload an image using standard http and file client. The key code for reference is here:
return this.file.readAsArrayBuffer(path, file).
then(blob => {
const imgBlob = new Blob([blob], { type: 'image/jpeg' } );
formData.append('image[file]', imgBlob);
return this.http.post(url, formData, headers).subscribe();
});
Hope it helps someone out there as it did for me.

Categories