NodeJS/Express4 endpoint generating corrupt xlsx file - angularjs

I am trying to create an endpoint using NodeJS/express 4 that generates and send to the user a xlsx file.
To create the xlsx file I am using the node-xlsx library.
var xlsx = require('node-xlsx');
var buffer = xlsx.build([{
name: pasta,
data: data
}]);
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader("Content-Disposition", "attachment; filename=" + pasta + ".xlsx");
res.write(buffer, 'binary');
return res.end();
And I am trying to download this file through an Angular app.
$http.post('https://endpoint/v1/' + folderName + '/reportExcel', {
responseType: 'arraybuffer'
})
.success(function(response) {
var blob = new Blob([response], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
var objectUrl = URL.createObjectURL(blob);
$window.open(objectUrl);
However, the file that is being downloaded is broken, so I can not open it.

Could it because you are using connect-livereload plugin? The plugin seems cause corrupted binary files being transferred. I've encountered the same, and solved it by adding 'ignore' when initiate connect-livereload plugin.
app.use(require('connect-livereload')({
ignore:['.xls', '.xlsx']
}));
See this post for detail: https://github.com/intesso/connect-livereload/issues/39

I posted an answer here: https://stackoverflow.com/a/41103999/1623249
Basically, you need to get the buffer from node-xlsx, convert it to base64 and then decode it in the client.

Related

How to save following content as PDF in Angularjs using FileSaver.js

I am unable to save this content as proper PDF using FileSaver.js
this is Angular code
$http(
{ url:root.api_root+'/appointments/generatePDF/'+$route‌​Params.id,
method:'GE‌​T'
}).then(function(r‌​es){ //
$log.log(res.data);
var blob = new Blob([res.data], { type: 'application/pdf' });
window.open(res.data);
// saveAs(blob, 'file.pdf');
});
this is TCPDF Backend code
$pdf->Output("php://output", 'F');
echo file_get_contents("php://output");
When downloading binary data such as PDF files, it is important to set the responseType property:
$http(
{ url:root.api_root+'/appointments/generatePDF/'+$route‌​Params.id,
method:'GE‌​T',
//IMPORTANT
responseType: 'blob'
}).then(function(r‌​es){ //
$log.log(res.data);
//var blob = new Blob([res.data], { type: 'application/pdf' });
//window.open(res.data);
var blob = res.data;
saveAs(blob, 'file.pdf');
});
If the responseType property is omitted, the XHR API defaults to processing the data as UTF-8 text. The process of decoding the data as UTF-8 text will corrupt binary files such as PDF or images.
For more information, see MDN Web API Reference - XHR ResponseType
Dependencies
AngularJS
FileSaver.js
Blob.js
Installation
Using bower: bower install angular-file-saver
Using npm: npm install angular-file-saver
Basic usage
Include ngFileSaver module into your project;
Pass both FileSaver and Blob services as dependencies;
Create a Blob object by
passing an array with data as the first argument and an object with set of options
as the second one: new Blob(['text'], { type: 'text/plain;charset=utf-8' });
Invoke FileSaver.saveAs with the following arguments:
data Blob: a Blob instance;
filename String: a custom filename (an extension is optional);
disableAutoBOM Boolean: (optional) Disable automatically provided Unicode text encoding hints.
You can do so by injecting FileSaver and Blob into the controller and then using the syntax as shown below:
angular.module('sample',['ngFileSaver'])
.controller('ConsultationDetailsController', ['$scope', 'FileSaver', 'Blob', function($scope, FileSaver, Blob){
$scope.download = function (fileName) {
$scope.isLoading = true;
downloadHttpService.getDocument(fileName)
.then(function (response) {
var data = response.data;
var status = response.status;
var header = response.headers();
var fileType = header['content-type'];
var blob = new Blob([data], { type: fileType });
FileSaver.saveAs(blob, originalFileName);
})
.catch(function (resp) {
// show error
})
.finally(function (data) {
// execute finally block.
});
};
}]);
if you want only the pdf type then you can hard coded define
fileType as 'application/pdf' like this var fileType= 'application/pdf';
Hope this solves your problem :)
Its work for me. Just try it.
$http(
{ url:root.api_root+'/appointments/generatePDF/'+$route‌​Params.id,
method:'GE‌​T'
}).then(function(r‌​es){
$log.log(res.data);
saveAs('data:application/pdf;base64,' + res.data, 'file.pdf');
});

can not upload the file with its extension and original path name using Multer and Node.js

I have one issue while uploading the file using Multer module from Node.js.I am explaining my code below.
server.js:
var multer = require('multer');
var upload = multer({ dest: './upload/' });
var cpUpload = upload.fields([{ name: 'images', maxCount: 1}]);
var app=express();
var server=http.createServer(app);
var admin=require('./route/route.js');
app.post('/uploadAll',cpUpload,function(req, res, next){
console.log('fiels',req);
})
supplierController.js:
var file=fileURL;
var curnum=(Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
var newPicpath=curnum+"_"+ file.name;
file.name=newPicpath;
console.log('file',file);
$scope.upload=Upload.upload({
url: '/uploadAll',
method:'POST',
data:{
images: file,
},
headers : {
'Content-Type': 'multipart/form-data'
},
}).success(function(data, status, headers, config) {
}).error(function(data, status) {
console.log('err file',data);
})
inside console message i am getting the below file data.
Blob
$ngfName:"vse123ertgf_1.jpg"
name:"vse123ertgf_1.jpg"
size:8607
type:"image/jpeg"
Here you can check my file name is containing one random number with it.When i am uploading the file the file is uploaded inside the given folder but taking another random number(i.e-75149c6770ea216b5ad8aafa7698539d) as its name and without extension(i.e-.jpg or png).Here also i am getting the error response inside error function in client side.I am using ng-file-upload to upload the file.Here i need the file should upload inside the required folder using its original name what its taking in client side.Please help me to resolve this issue.
Satya. The issue you are facing is very common. Please read the following post for some beautiful insight. I had the same issue and I resolved it using this post. For further issue please comment below, will help you out.

download .zip file from server in nodejs

I am using MEAN, in which I want to allow user to download zip file from server.
So basically I have to do following things:
Create csv files from certain data.
Store that file into some directory.
Compress these file to zip.
When a user clicks on the button, zipped file should be downloaded and readable.
I have achieved 1,2,3 completely, and 4 partially. In this I have been able to successfully download zip file, but this file is in corrupted format and I am not able to read this file.
My code for download functionality is here:
html:
Download CSV Reports
angular part:
$scope.downloadFiles = function() {
$http({
method: 'GET',
url: '/download/csv/files'
}).
success(function(data, status, headers, config) {
var anchor = angular.element('<a/>');
anchor.attr({
href: 'data:attachment' + encodeURI(data),
target: '_blank',
download: 'filename.zip'
})[0].click();
}).
error(function(data, status, headers, config) {
alertify.error(data);
});
};
NodeJS:
var path = require('path'),
fs = require('fs');
exports.downaloadAllCsv = function(req, res) {
var file = 'local path to my zip file',
filename = path.basename(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type:',' application/zip');
var filestream = fs.createReadStream(file);
filestream.pipe(res);
};
I used an npm library called express-zip (found here: https://www.npmjs.com/package/express-zip)
Using Node 4.X and Express 4.X, I can download a zip file from my browser. Getting it to work through Angular is what lead me to my own question:
Client download of a server generated zip file
Given all of that, here is my server code that worked:
Node (4.X) code with express-zip:
router.get('/bulkdownload',function(req,resp){
var titles = req.query.titles || [];
if ( titles.length > 0 ){
utils.getFileLocations(titles).
then(function(files){
let filename = '/tmp/zipfile.zip';
// .zip sets Content-Type and Content-disposition
resp.zip(files,filename);
},
_errorCb)
}
});
The utils.getFileLocations(titles) returns a promise where files is an array like this:
[{path: '/path/to/file/file.abc',name:'file.abc'},{...},{...},...]
My .zip file is not corrupted, and is readable.

Upload image to server angularjs

I need to upload an image taken from my mobile device to my server. I found the angular-upload library to which makes reference. I need to do is to transform the image base 64, send it by post to my server because the server is where I will work with her. And the other, send from my server and work it from the application to run.
var server = URL_BASE+'addView/';
var trustAllHosts = true;
var ftOptions = new FileUploadOptions();
ftOptions.fileKey = 'file';
ftOptions.fileName = $scope.imagen.substr($scope.imagen.lastIndexOf('/') + 1);
ftOptions.mimeType = 'image/jpeg';
ftOptions.httpMethod = 'POST';
console.log(ftOptions);
$cordovaFileTransfer.upload(encodeURI(server), $scope.imagen, ftOptions, trustAllHosts)
.then(function(result) {
console.log(result)
}, function(err) {
// Error
console.log(err);
}, function (progress) {
});
ionic file transfer
I'm personally using Cordova file transfer for upload & download content from a server.
Base64 encoding
Don't know where is your image stored and how you retrieve it, but, either you specify that the image is base64 encode into the HTML file delimiter
OR
You transform your image using a canvas
See that post for more info : https://stackoverflow.com/a/20285053/3687474
You haven't specified what you really need so:
Here you have a factory
//Factory you register on your module
angular
.module('myApp')
.factory('sendBase64Image', sendBase64Image)
function sendBase64Image($http) {
var urlBase; //url to be filled in
var base64 = {};
base64.sendBase = function (baseImg) {
var request = $http({
method: "post",
url: urlBase,
headers: {
'Content-type': 'application/json'
},
data : baseImg
});
}
return base64;
}
You should then inject it via dependency injection to your controller and perform call to the server.
If you want to do something with a response use success() method to handle promise response.

Outputting a PDF (created with FPDF) in AngularJS

I am using FPDF to create a PDF on a Laravel backend that serves Angular. I have created it in the normal FPDF way and I am unsure how to send the file response back to Angular.
I read here about generall how to go about it by configuring my $http request as below:
return $http({url: '/api/print/class-list', method: "POST", data: {data: data}, headers: {'Accept':'application/pdf'}, responseType: 'arrayBuffer'})
.then(function(response)
{
console.log(response.data);
var file = new Blob([response.data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
var content = $sce.trustAsResourceUrl(fileURL);
return content;
}
I have injected $sce in the service and i am outputting the content in an embed tag. The tag just shows an empty PDF. I am wondering what the problem could be. Also, on the Laravel side, once I am done creating the PDF by writing $pdf->Output("page","D"), is there a way i should write return something so that it can be returned to Angular?
Also, when i console response, it kindof returns blob or some pdf stuff, and a number of errors after that like:
"Warning: Unsupported feature "unknown"

Resources