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');
})();
Related
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);
});
}
File is not downloading at browser. I'm preparing the file and writing it to output stream of response.
Rest API is there:
#RequestMapping(value = "/export-companies",
method = {RequestMethod.GET, RequestMethod.HEAD})
#Timed
public void downloadCompanies(HttpServletResponse response) throws URISyntaxException {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Sample sheet");
Map<String, Object[]> data = new HashMap<String, Object[]>();
data.put("1", new Object[] {"Emp No.", "Name", "Salary"});
data.put("2", new Object[] {1d, "John", 1500000d});
data.put("3", new Object[] {2d, "Sam", 800000d});
data.put("4", new Object[] {3d, "Dean", 700000d});
Set<String> keyset = data.keySet();
int rownum = 0;
for (String key : keyset) {
Row row = sheet.createRow(rownum++);
Object [] objArr = data.get(key);
int cellnum = 0;
for (Object obj : objArr) {
Cell cell = row.createCell(cellnum++);
if(obj instanceof Date)
cell.setCellValue((Date)obj);
else if(obj instanceof Boolean)
cell.setCellValue((Boolean)obj);
else if(obj instanceof String)
cell.setCellValue((String)obj);
else if(obj instanceof Double)
cell.setCellValue((Double)obj);
}
}
try {
ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
workbook.write(outByteStream);
byte [] outArray = outByteStream.toByteArray();
response.setContentType("application/ms-excel");
response.setContentLength(outArray.length);
response.setHeader("Expires:", "0"); // eliminates browser caching
response.setHeader("Content-Disposition", "attachment; filename=template.xls");
OutputStream outStream = response.getOutputStream();
outStream.write(outArray);
outStream.flush();
workbook.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
From front end (using Angular JS):
(function() {
'use strict';
angular
.module('MyApp')
.factory('CompanyExportService', CompanyExportService);
CompanyExportService.$inject = ['$resource'];
function CompanyExportService ($resource) {
var service = $resource('api/export-companies', {}, {
'get': {
method: 'GET',
isArray: false
}
});
return service;
}
})();
File contents are there in response as non-readable format. But file is not downloaded at browser.
Angular will receive the file contents mere character sequences. You need to create a file from these characters and initiate the browser download in frontend.
You can do it like this -
var blob = new Blob([data],
{type: 'application/vnd.openxmlformat-officedocument.spreadsheetml.sheet;'});
saveAs(blob, fileName);
where data is the response you received form your API. The saveAs function is part of FileSaver.js library. Although you can look on how to manually do that but why reinvent the wheel?
Downloading files with XHR is problematic. As long as you do only GET requests, there exists much simpler approach to trigger browser to download file.
Use JavaScript native method window.open(url).
It does work well in all browsers including IE9.
In code below, I use $window, which is Angular's proxy for native window object.
Example for your code could be like:
(function() {
'use strict';
angular
.module('MyApp')
.factory('CompanyExportService', CompanyExportService);
CompanyExportService.$inject = ['$window'];
function CompanyExportService ($window) {
var exportUrl = 'api/export-companies';
return {
download: download
}
function download() {
$window.open(exportUrl);
}
}
})();
Note that this action is out of scope of Angular, you can't do much about error handling or waiting till the file will be downloaded. Might be problem if you want to generate huge Excel files or your API is slow.
For more details, read question: Spring - download response as a file
Update:
I've replaced window.location.href with window.open() which seems to be better choice for downloading files.
If your API will throw an error page instead of file, window.location.href will replace current page (thus losing its state). $window.open() however will opens this error in new tab without losing current state of of application.
You can download file in new tab. Modern browser are closing them automatically when downloading is completed.
By opening new window you get reference to it, when downloading is completed then window.closed is set to true.
Unfortunatelly you need to check from time-to-time this param inside interval ...
var newWindowRef = $window.open(url, name);
if (newWindowRef) {
if (newWindowRef.document.body) { // not working on IE
newWindowRef.document.title = "Downloading ...";
newWindowRef.document.body.innerHTML = '<h4>Your file is generating ... please wait</h4>';
}
var interval = setInterval(function() {
if (!!newWindowRef.closed) {
// Downloading completed
clearInterval(interval);
}
}, 1000);
} else {
$log.error("Opening new window is probably blocked");
}
Tested and works on Chrome v52, FF v48 and IE 11
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);
}
}
How would it be possible to get the URL hash fragment from route params in $routeChangeStart.
$scope.$on('$routeChangeStart', function (event, next, current) {
// trying to get the url hash fragment from <next> param here
// e.g. to_url_function(next) -> '/my_path/1'
});
Receiving the URL hash fragment would be easy using $locationChangeStart but this is not an option for me.
dasboe: I think I'm answering your question.
I have a app with an authentication/authorization check in the $routeChangeStart event handler. If not authenticated, I present user with modal login page. I want a successful login to send them to their original destination (Beauty of $routeChangeStart is that it will run again and check authorization after the successful login). I save the path built from the next in a user session service that is injected into the modal login controller.
here is the event handler
//before each route change, check if the user is logged in
//and authorized to move onto the next route
$rootScope.$on('$routeChangeStart', function (event, next, prev) {
if (next !== undefined) {
if ('data' in next) {
if ('authorizedRoles' in next.data) {
var authorizedRoles = next.data.authorizedRoles;
if (!SessionService.isAuthorized(authorizedRoles)) {
event.preventDefault();
SessionService.setRedirectOnLogin(BuildPathFromRoute(next));
if (SessionService.isLoggedIn()) {
// user is not allowed
$rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
} else {
// user is not logged in
$rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
}
}
}
}
}
});
Here is the function that builds the path from the next object
function BuildPathFromRoute(routeObj)
{
var path = routeObj.$$route.originalPath;
for (var property in routeObj.pathParams)
{
if (routeObj.pathParams.hasOwnProperty(property))
{
var regEx = new RegExp(":" + property, "gi");
path = path.replace(regEx, routeObj.pathParams[property].toString());
}
}
return path;
}
Notes:
I'm not keen on my $$route reliance, but I couldn't find any other way to do it. Maybe I missed something easier. I may be inviting trouble in the long term.
The preventDefault() will not work on AngularJS versions before 1.3.7 (see event.preventDefault() not working for routeChangeStart in angularjs app).
Standard caveat: This is all client side and subject to abuse. Make sure authentication/authorization happens server side.
The next Route object (from the event handler) also has a params property. I'm not sure if I should spin through its properties like I do with pathParams.
If you don't want to use hasOwnProperty, you could take advantage of the $$route.keys to get the names of the pathParams fields names:
function getPathFromRoute(routeObj)
{
var path = routeObj.$$route.originalPath;
var keys = routeObj.$$route.keys;
var value;
for (var i = 0; i < keys.length; i++) {
if(angular.isDefined(keys[i]) && angular.isDefined(keys[i].name)){
value = routeObj.pathParams[keys[i].name];
var regEx = new RegExp(":" + keys[i].name, "gi");
path = path.replace(regEx, value.toString());
}
}
return path;
};
Don't use object fields with $$ prefix like in previously given answers, because it's a prefix used by AngularJS for private properties. Use this method for get url from route (not tested):
var buildPathFromRoute = function (route) {
// get original route path
var path = route.originalPath;
// get params keys
var keysLength = route.keys.length;
for (var i=0; i<keysLength; i+=1) {
var param = route.keys[i];
// optional params postfix is '?'
var postfix = param.optional ? '\\?' : '';
var replaceString = ':' + param.name + postfix;
var regex = new RegExp(replaceString, 'g');
var paramValue = route.params[param.name].toString();
// replace param with value
path = path.replace(regex, paramValue);
}
path = path.replace(/\:\S+?\??/g, '');
return path;
};
Folks: Creating an app in angular and node webkit - where users queue up files for downloading, navigate to their dashboard view and this initiates the downloads.
I've created a service which holds an object of the files data:
..
var downloadObj = {};
// fileObj = {'name':'The file name'; 'download_progress' : dlProgress}
showcaseFactory.myDownloads = function(eventId, fileObj) {
if(eventId){
console.log('update the object');
downloadObj['event_'+eventId] = fileObj;
}
console.log(downloadObj);
};
showcaseFactory.getDownloads = function() {
return downloadObj;
};
..
When the dashboard view loads - ng-repeat loops over $scope.downloadFiles which references this object returning the data.
<div ng-repeat="file in downloadFiles">
<div><span>{{file.name}}</span> [{{file.download_progress}}%]</div>
</div>
I've created a custom module which utilises node_modules to perform the download of the files:
nwjsDownloadFactory.commenceDownload = function(event_id, url, dest, cb) {
var http = require('http');
var fs = require('fs');
var statusBar = require('status-bar');
var path = require('path');
// THIS UPDATES THE OBJECT AND DISPLAYS FINE --------- >>
var id = 7;
var testFileObj = {
'name' : 'This is the file name prior to the download...',
'download_progress' : 10
};
ShowCase.myDownloads(id, testFileObj);
// <<< THIS UPDATES THE OBJECT AND DISPLAYS FINE ---------
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
bar = statusBar.create({ total: response.headers['content-length'] })
.on('render', function (stats) {
// var percentage = this.format.percentage(stats.percentage);
// console.log(event_id + '....' + percentage);
var id = 7;
var testFileObj = {
'name' : 'This is the new file name during the download...',
'download_progress' : 35 // this will be replaced with percentage
};
ShowCase.myDownloads(id, testFileObj);
});
response.pipe(bar);
}).on('error', function(err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (cb) cb(err.message);
});
}
QUESTION: Prior to the line var request = http.get(url, function(response) the object gets updated, and the changes are reflected in the UI. However, I need to constantly update the object with download complete % so I can create a progress bar.. However, as this asynchronous function executes, the object
appears to be updating - see the attached screen shot - but the UI is not reflecting this.
Can somebody please steer me in the right direction - I need the object to update during the function bar = statusBar.create({ and for the changes to reflect in the UI..
Call $scope.$apply() after making changes to your model to notify Angular that it has to update the UI.
showcaseFactory.myDownloads = function(eventId, fileObj) {
if(eventId){
console.log('update the object');
downloadObj['event_'+eventId] = fileObj;
$scope.$apply();
}
console.log(downloadObj);
};
If you use Angular's $http object, this is handled automatically for you, but if you update your model from other asynchronous callbacks, you have to take care of it yourself.
See this blog post and this documentation page for more in-depth explanations about what's going on.