I need to download a file from the server. The file is stored in the database. I have a cs controller that serves a file back to UI. The server GET call looks like this:
http://server/api/controllername/fileid/data
It does work when I run that link in the Browser - the file comes down and goes into the download area (Chrome). But when I send the same command from my Angualar code I dont see any file. The console reports that my request was successful (code 200), but I just dont see anything. Please let me know what code fragments to post to make it easier to help.
Thanks
Create a link to the resource, and don't handle it with ajax.
If you make the link open in a new tab, the tab will automatically close after it realises it was just opened to download a file in most modern browsers.
Try this code:
var a = document.createElement('a');
a.href = "http://server/api/controllername/fileid/data";
a.click();
You can compose the address concatenating variables and text.
The file probably downloads correctly as a byte[] to the calling it but that would be useless to the user - as was my problem.
In my case I needed to download a file with a complex set of parameters. This example JavaScript uses a post request and creates a form (and posts it) with any JavaScript object that you give it. This code may help if you simplified it:
private open(verb, url, data, target)
{
var form = document.createElement("form");
form.action = url;
form.method = verb;
form.target = target || "_self";
if (data) {
this.createFormParameters(form, "", data);
}
form.style.display = 'none';
document.body.appendChild(form);
form.submit();
}
private createFormParameters(form, key, value) {
// recursive algorithm to add parameters (including objects and arrays of objects) to a custom form
if (typeof value === "object") {
for (var item in value) {
if (Array.isArray(value[item])) {
for (var arrayItem in value[item]) {
this.createFormParameters(form, (item + "[" + arrayItem + "]."), value[item][arrayItem]);
}
continue;
}
var input = document.createElement("textarea");
input.name = key + item;
input.value = value[item];
form.appendChild(input);
}
}
else
{
var input = document.createElement("textarea");
input.name = key;
input.value = value;
form.appendChild(input);
}
}
Related
I want to save somes PDF created with 'survey-pdf' on my disk.
Actually, i can send the PDF but i can't save it on my disk.
My final code :
return surveyPDF.save(filename);
Someone can help me ?
Thank you
Can you try
await surveyPDF.save(filename)
?
.save seems to be an asynchronous function that downloads the PDF file.
From the docs
Call save method of surveyPDF object to download file in browser. This is asynchronous method
#2 If the first method doesn't work, you can try this
function savePdfAsString() {
const surveyPDF = new SurveyPDF.SurveyPDF(json);
surveyPDF.data = survey.data;
surveyPDF
.raw("dataurlstring")
.then(function (text) {
//var file = new Blob([text], {type: "application/pdf"});
var a = document.createElement("a");
//a.href = URL.createObjectURL(file);
a.href = text;
a.download = "surveyAsString.pdf";
//document
// .body
// .appendChild(a);
a.click();
});
}
Here you are using the .raw function to transform the PDF into a dataurlstring and then downloading that. Here's the docs for this
*Not tested
I have recently learned AngularJS. I started a small project. I was able to extract data from a json file. My current task is to be able to extract data from multiple json files. How can I do this?
I made my first json file this way:
$http.get("personel.json")
.then(function(gelen) {
$scope.personeller = gelen.data;
});
I have 9 more json files that I need to take, but I want to see the data of the file I'm calling
$http.get("1.json")
.then(function(veri1) {
$scope.x1 = veri1.data;
});
the other files are named "1.json, 2.json, 3.json ....... 9.json"
How can I change the location of the 1.json in the top code block?I am sorry for my English.The first time I am writing to a foreign forum. Thanks in advance
$scope.getdetail = function(detail) {
$scope.result = detail;
$http.get($scope.result.id + ".json")
.then(function(veri1) {
$scope.x1 = veri1.data;
});
}
I solved my problem this way thanks.
You can wrap the $http call in a function and pass in the filename you wish to retrieve like this:
Edit I modifed the code here adding a promise to handle issues that could arise from asynchronous requests
$scope.getFile = async function(fileName){
return new Promise((res, err) => {
$http.get(fileName).then(function(result){
res(result.data);
})
})
}
$scope.file1 = $scope.getFile("1.json");
$scope.file2 = $scope.getFile("2.json");
$scope.file3 = $scope.getFile("3.json");
$scope.file4 = $scope.getFile("4.json");
$scope.file5 = $scope.getFile("5.json");
$scope.file6 = $scope.getFile("6.json");
$scope.file7 = $scope.getFile("7.json");
$scope.file8 = $scope.getFile("8.json");
$scope.file9 = $scope.getFile("9.json");
If the files are sequential and numeric you could also use this to pull all the data from the file into a single array using a for loop.
$scope.returnedFiles = [];
for(i = 0; i < 9; i++){
$scope.getFile(i + ".json").then(fileData => {
$scope.returnedFiles.push(fileData);
});
}
This question has been asked a fair bit before, but none of the solutions I've seen seem to work, potentially because of the way I stream the file back to the browser. The CSV I ultimately want is in a private S3 bucket and because of security middleware, I have to get it via a NodeJS endpoint. The code for the API is below.
exports.download = function(req, res) {
var recording = req.vsRecording,
s3 = new AWS.S3();
if(recording.data_uri){
try{
res.set('Content-Type', 'application/octet-stream');
var fileStream = s3.getObject({Bucket: 'processing-dispatched', Key: recording._id + '/aggregated.csv'}).createReadStream();
fileStream.pipe(res);
}
catch(err){
res.status(500).json({error: err});
}
}
else {
res.status(500).json({error: 'Recording does not have a report file.'});
}
};
This works perfectly and I can get the content of the file back to the browser. When it goes wrong is trying to get that content into be opened as a file download. Is there a special way to handle downloading streams?
The closest I've got is this code on the client, which sometimes seems to work on localhost if I turn my adblocker off - but does not work in production.
$scope.download = function(){
Report.download($state.params.recordingId).then(function(data){
var csvContent = "data:text/csv;charset=utf-8," + data.toString();
var encodedUri = encodeURI(csvContent);
window.open(encodedUri);
});
Report.download is just an angular service wrapper around my Node endpoint, it returns a promise and resolves the content of the file in the data variable.
reason might be the browser blocking the new window.
Allow all sites to show pop-ups in browser setting.
you can try thing in different ways create a file in node with fs and return url to the Front-end
or
you can Try the following code
$scope.download = function() {
Report.download($state.params.recordingId).then(function(data) {
var csvContent = "data:text/csv;charset=utf-8," + data.toString();
var a = document.createElement('a');
a.href = "data:application/csv;charset=utf-8," + csvContent;
a.setAttribute('download', "abc.csv");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
}
I am very new at this and I am trying my best to work it out. It would be glad if someone can really save my day.
Trying to call an API using a trigger and get data using google scripts this is the best I came up with.
Basically I have an api which gives me objects if I putit in Postman. All I need to do it get those object in google spreadsheets.
I have tried onOpen function which was giving me an error of" You do not have permission to call Fetch".
So have been trying with on edit of first column as "Get Data" so the api can be called.
Thanks in advance
function onEdit(e) {
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Sheet1") { //checks that we're on the correct sheet
var r = s.getActiveCell();
//Updates timestamp for lead entry and meetings.
var currentCellValue = r.getValue();
var user = Session.getEffectiveUser();
if (r.getColumn() == 1 && (currentCellValue == 'Get Data')) { //checks the column
var nextCell = r.offset(0, 4);
if (nextCell.getValue() == '') { //is empty?
nextCell.setValue(Utilities.formatDate(new Date(), "GMT+5:30", "dd/MM/yyyy HH:mm:ss")).setComment(user);
var url = "My API";
var headers = {
"Content-Type": "application/json",
"Authorization": "userkey"
};
var options = {"method":"GET","headers": headers
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response[0]);
}
}
}
}
This appears to be a long standing issue that still hasn't been taken care of, see here
Someone in the thread mentions
But, using a custom function name like myOnEdit(), and connecting it
to the onEdit event manually, totally works!
function myOnEdit(e) { ... var x = fetchUrlApp.fetch(...); ... }
So you have to create myOnEdit and then put an onEdit trigger on it, either via Resources > Current Project's triggers or via the trigger service.
I'm searching or a way to open a URL with two POST parameters. My only option now is writing a small exe which creates a form in a WebBrowser control then auto-clicks a button, which is horrible. Is there a better way I can do this?
You could create an HTML File with the following javascript:
<script type="text/javascript">
<!-- The function below does a post without requiring a form or the click of a button -->
function postwith (to,p) {
var myForm = document.createElement("form");
myForm.method="post" ;
myForm.action = to ;
for (var k in p) {
var myInput = document.createElement("input") ;
myInput.setAttribute("name", k) ;
myInput.setAttribute("value", p[k]);
myForm.appendChild(myInput) ;
}
document.body.appendChild(myForm) ;
myForm.submit() ;
document.body.removeChild(myForm) ;
}
</script>
Example Usage:
<script type="text/javascript">
function delconfirm(id){
if(confirm('Are you sure?'))
{
postwith('http://somesite.com/webpagetorecievepost.php',{KEY:VALUE,KEY:'STRING VALUE'});
}
}
</script>
You can have as many KEY:VALUE pairs as you like.
Once you have this html file you can modify and open it in internet explorer.
There are web browser automation tools that can drive IE, for instance Selenium. Selenium is scriptable, and has drivers for the major browsers. I've only used selenium for this kind of thing, driven by java code; there are alternatives.
There are also Windows GUI automation tools, for instance AutoIT, that can open a given program and manipulate GUI elements.
I got this working so you can open a standard .html file with a query string to forward the parameters to a URL.
function postFromQueryString(url) {
// grab params from query string into KVP array
var postParams = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
postParams.push(hash[0]);
postParams[hash[0]] = hash[1];
}
if(postParams.length === 0) {
alert('No parameter was passed');
window.close();
return;
}
// create a form
var formToPost = document.createElement("form");
formToPost.method="post";
formToPost.action = url;
// add params to form
for (var k in postParams) {
var postInput = document.createElement("input");
postInput.setAttribute("name", k);
postInput.setAttribute("value", postParams[k]);
formToPost.appendChild(postInput);
}
document.body.appendChild(formToPost);
formToPost.submit();
document.body.removeChild(formToPost);
}
To call it onLoad:
(function () {
// build dynamic form and post
postFromQueryString('http://yourUrlToPostTo.aspx');
})();