How to post a request and download file to disk with angular? - angularjs

In angular, I want to download a text file containing a csv of userdata. Usually I have a form with a post action, but I want the user to stay on the same page, but return the csv data without any page referesh. The following is my post command:
$http({
url: "api/getUserData",
method: "POST",
data:{user_id:app.user_id}
}).success(function(data, status, headers, config) {
// data gets returned here
}).error(function(data, status, headers, config) {
$scope.status = status;
});
My problem is, the "data" that comes back from the post is a csv file. how can I get the data to actually "download" to the user's computer instead of living in the javascript? Is this even possible?

Here is the link to solution. It uses HTML5 FileSaver API to save the file as BLOB

You can do this :
Create temporary anchor ,
encode, your data & name your file using download attribute,
and then, fire a click event on it.
finally, remove the inserted element .
$http({
url: "api/getUserData",
method: "POST",
data:{user_id:app.user_id}
}).success(function(data, status, headers, config) {
// data gets returned here
var anchor = angular.element('<a/>');
angular.element(document.body).append(anchor); // Attach to document
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'myFileName.csv'
})[0].click(); // fire a click event.
anchor.remove(); // Clean it now ...
}).error(function(data, status, headers, config) {
$scope.status = status;
});

Related

AngularJS HTTP Post Conditional in Data or Params

Understand that for POST method, the key - Data is being used instead of Params, however if the data is being used for filtering is it possible to have conditions for these Data ?
var proxyData = {
lecturer_id: "e9d0bea0-76cb-11e8-adc0-fa7ae01bbebc",
status: ["pending", "accepted"]
};
try {
$http({
method: $scope.proxyMethod,
url: url,
data: proxyData
}).
success(function(data, status, headers, config) { }).
error(function(data, status, headers, config) { });
In the above example, I would like to filter out lecturer_id with the exact match, but with status of either "pending" or "accepted".
Is it possible to do something like GET params - "?status=pending,accepted"
Thanks in advance and sorry if my question has any misunderstanding of how AngularJS works as I am still new to it.

large files failing download in nodejs

I have a service that builds a csv file, and returns it to the user. Currently using expressjs v4.14, nodejs v8.7.0. My problem is that I get a download failed due to 'network error' in chrome when I call the service for it to create a large csv file. With smaller files, the service works fine. I can also browse to the /temp/ folder, and the entire expected file exists. In each case of 'things i tried', I was able to download smaller files but not the large ones.
Service:
download.post('/csv', (req, res, next) => {
res.status(200).header('Content-Type', 'text/csv');
const newUUID = uuid.v1();
let ws: WriteStream = fs.createWriteStream(`${__dirname}/../../temp/${newUUID}.csv`);
ws.on('finish', () => {
res.download(`${__dirname}/../../temp/${newUUID}.csv`);
});
//csv file built here
ws.write('huge stuff easily 50k rows and 10 mb file');
ws.end();
});
Chrome Error:
Chrome's network tab and developer console do not give me any indication of what happened. This download popup is all I get. I cleared everything in cookies/cache just in case and it did not help.
Things I tried:
writing chunks directly to response stream.
using readable stream https://nodejs.org/api/stream.html#stream_readable_streams , converting String into bytes and piping it.
creating a file locally (writestream) and streaming it back (readstream pipe into res)
res.download(file) after writestream creating local file ended
Update:
Ended up trying the service from postman and it worked, so I think it is an angularjs issue.
Angularjs
$http({
cache: false,
url: "/download/csv",
headers: {
'accept': 'text/csv'
},
method: 'POST',
data: {
rows: rows,
title: title ? title : ''
}
}).success(function (data, status, headers, config) {
var anchor = angular.element('<a/>');
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'csv_info.csv'
})[0].click();
}).error(function (data, status, headers, config) {
});
Turned out to be a limitation from href attribute from the anchor tag created in angularjs. This was solved using FileSaver:
$http({
cache: false,
url: "/download/csv",
headers: {
'accept': 'text/csv'
},
method: 'POST',
data: {
rows: rows,
title: title ? title : ''
}
}).success(function (data, status, headers, config) {
var file = new File([data], "info.csv", {type: "text/csv;charset=utf-8"});
saveAs(file);
}).error(function (data, status, headers, config) {
});

Sending data from form to POST request in Angular

I want to make a POST request using Angular. I am using ng-submit to submit the form to the controller where I access the factory to make the request using:
$http.post('/droplets', data)
I need the data from the form fields to put in the "data" variable above to send to my API but I can't work out how to do this when it is more than one field. How is this done?
Try this...
$http({
url: '/droplets',
method: "POST",
data: JSON.stringify({application:app, from:data1, to:data2}),
headers: {'Content-Type': 'application/json'}
}).success(function (data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
Ref:https://docs.angularjs.org/api/ng/service/$http

Http progress function?

$http({
url: Config.ApiURL + "/site/go",
method: "POST",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: $.param(testimony)
}).progress(function (data, status, headers, config) { //Not sure about this line
console.log('progressing');
}).success(function (data, status, headers, config) {
console.log('success');
});
I want to display something before it successes or error, so im not sure about .progress part, i just inserted it there as an example and for you to imagine my problem.. is it possible? is there a built-in function for that?
BTW, im new to angular. TIA :)
According to some post I found on github (https://github.com/angular/angular.js/issues/1934 , see the post from 26th april 2014), you should be able to do it like that :
$http({method: 'GET', url: '/someUrl',progress:trackProgress}).then(function(result){
// handle result
});
Where tarckProgress would be a callback to call to handle the progress state.
If you want to show the progress spinner / bar, and in addition to that if you want to show something else, you can use angular-loading-bar

Is it possible to send base64 image to an amazon s3 bucket via ngFileUpload post?

I have a working script that when the file input changes, pick the files, sign their upload data in my django backend, and upload it from the frontend directly to my s3 bucket. It's working great. I'm using ng-file-upload to do it.
var doSignUrl = function(image, success, error){
$http({
url: scope.signUrl,
params: {
s3_object_name: image.name,
s3_object_type: image.type
},
method: 'get'
}).success(success).error(error);
};
var getUploadConfig = function(image, data){
return {
url: data.url,
method: 'POST',
fields : {
key: data.path,
AWSAccessKeyId: data.aws_access_key_id,
acl: data.acl,
policy: data.policy,
signature: data.signature,
"Content-Type": image.type != '' ? image.type : 'application/octet-stream',
filename: data.file_name
},
file: image,
};
};
var doUpload = function(image){
doSignUrl(image, function(signData){
Upload.upload(getUploadConfig(image, signData)).progress(function(e){
doProgress(image, parseInt(100.0 * e.loaded / e.total))
}).success(function(data, status, header, config){
doSuccess(image, signData.url+'/'+signData.path);
}).error(function(data, status, header, config){
doError(image);
});
}, function(data, status, header, config){
console.log(status);
console.log(data);
});
}
for each file the file picker selects i call doUpload(file)
But my real objective is to crop the image in frontend using canvas before to upload. The problem is that when you crop image using canvas, the result is a base64 encoded image, not a file. So my final question is: is it Possible to upload this base64 image directly to s3?
With a lot of research i found out that you can send a blob instead of a file unsing ngFileUpload to s3.
I used this library to convert my base64 to a blob, and then passed the generated blob instead of the file in the Upload.upload() file parameter.

Resources