serialize a client-side made string to a server-side file angularJS - angularjs

So i'm building a string which is actually an xml file. Since i can't save any file from client-side for security issues, i'd like to save this string in a xml file server-side.
i've read about $http method or upload plugin but it seems a bit a complicated for just sending a string to my server.
is there an easier way to do it?
For informative purpose, here is my code :
$scope.addBlock = function(){
if($scope.parentblock == null)//creation of a lvl1 element
{
var div = document.createElement("div");
//xml creation
var elmt = document.createElement($scope.selectedtype.tagname);
//
div.setAttribute('id',$scope.blocktitle);
div.setAttribute('lvl',0);
var path = '/'+$scope.selectedtype.tagname;
div.setAttribute('path',path);
div.innerHTML = '<h1>' + $scope.blocktitle + '</h1><p> path : '+ path + '</p>';
if($scope.blockvalue)
{
div.innerHTML = div.innerHTML + '<p>' + $scope.blockvalue + '</p>';
//adding value to xml tag
elmt.innerHTML = $scope.blockvalue;
//
}
document.getElementById('blocks').appendChild(div);
//xml adding
doc.appendChild(elmt);
console.log(doc);
//
$scope.blocks.push([$scope.blocktitle,$scope.selectedtype.tagname,$scope.parentblock,path]);
}
else //creation of a lvl n element
{
var div = document.createElement("div");
//xml creation
var elmt = document.createElement($scope.selectedtype.tagname);
//
div.setAttribute('id',$scope.blocktitle);
var lvl = Number(document.getElementById($scope.parentblock[0]).getAttribute('lvl'))+1;
div.setAttribute('lvl',lvl);
var path = ($scope.parentblock[3]+'/'+$scope.selectedtype.tagname);
div.innerHTML = '<h2>' + (new Array(lvl + 1).join("&nbsp")) + $scope.blocktitle +
'</h2><p>' + (new Array(lvl + 5).join("&nbsp")) + ' path : '+ path + '</p>';
if($scope.blockvalue)
{
div.innerHTML = div.innerHTML + '<p>' + (new Array(lvl + 5).join("&nbsp")) +
$scope.blockvalue + '</p>';
//adding value to xml tag
elmt.innerHTML = $scope.blockvalue;
//
}
document.getElementById($scope.parentblock[0]).appendChild(div);
//xml adding
doc.getElementsByTagName($scope.parentblock[1].toLowerCase())[0].appendChild(elmt);
//
$scope.blocks.push([$scope.blocktitle,$scope.selectedtype.tagname,$scope.parentblock,path]);
}
//console.log(doc);
}
I need to send doc to my server.
EDIT :
i really need to send an xml since is a iso19110-normalized file that i have to save.
I tried this :
$http({
method: 'POST',
url: 'save.php',
data: { 'doc' : doc.outerHTML },
headers: {'Content-Type': 'text/xml'}
})
.success(function(data){
alert(data);
})
.error(function(){
alert('fail');
});
and this in php :
file_put_contents('test.xml', $_POST['doc'])
but i've got "index doc undefined" ...
I also tried
$http.post('save.php',doc).success(function() {
return console.log('uploaded');
});
but i got 'Converting circular structure to JSON'
So i think my problem come from the location of the data. I can't figure where it is...

If you need to send a lump of text to your server (over http) then you should use the $http.post() method. Its easy to use and works like a charm. You can receive and save the data on the server in any number of ways, presumably you have this bit worked out?
The real issue from your question, imo, is whether you really need to be sending xml? A much easier way of sending your data would be to use JSON. Then you don't need to go through all that document building rigmarole. Instead you can just build a javascript object and send it using the $http.post() method letting angular do all the work for you.
var doc;
doc = {
id: $scope.blocktitle,
lvl: 0
// rest of your doc structure here
};
$http.post('/my-url/upload/doc', doc).success(function() {
return console.log('uploaded');
});

Related

http.get attempts to retrieve image when parsing when I do not need it to

function getHTMLSource(url) {
return $http.get(url).then(function(response) {
var html = response.data;
url = getDetailPage(html)
return url ;
}
)};
getHTMLSource('http://www.footpatrol.co.uk/s:282524/search=282524/')
Whenever I attempt the above code, I get the following error message in my console GET http://localhost:9000/templates/footpatrol.co.uk/_assets/images/content/footpatrol_logo.png 404 (Not Found).
The image appears to exist at http://www.footpatrol.co.uk/templates/footpatrol.co.uk/_assets/images/content/footpatrol_logo.png but as I am running the scipt on localhost with Chrome's Allow-Control-Allow-Origin plugin, it appears to not play nicely. I do not want to GET the image I just want the source code, is there anyway around this?
UPDATE: I think it might be my parser causing the problem, because the error message is thrown here
function getDetailPage(html) {
var temp = document.createElement('div');
temp.innerHTML = html;
var a = temp.querySelector('a[class*=\'fp-product-thumb-link\']');
var partOfUrl = a.href;
var splitUrl = partOfUrl.split('/');
var url = 'http://www.footpatrol.co.uk/' + splitUrl[3] + '/' + splitUrl[4];
var url = 'http://www.footpatrol.co.uk/' + splitUrl[3] + '/' + splitUrl[4];
$log.debug('Detail page url found: ' + url);
return url;
}
Instead of creating an element, use the DOMParser API:
function getDetailPage(html) {
//var temp = document.createElement('div');
//temp.innerHTML = html;
var parser = new DOMParser();
var temp = parser.parseFromString(html, "text/html");
var a = temp.querySelector('a[class*=\'fp-product-thumb-link\']');
//var partOfUrl = a.href;
//console.log(partOfUrl);
//var splitUrl = partOfUrl.split('/');
//var url = 'http://www.footpatrol.co.uk/' + splitUrl[3] + '/' + splitUrl[4];
var elem = angular.element(a);
var url = 'http://www.footpatrol.co.uk/' + elem.attr('href');
console.debug('Detail page url found: ' + url);
return url;
}
Detail page url found: http://www.footpatrol.co.uk//footwear/282524-air-retro-15-obsidian.html

how to set a unique aws S3 file name?

I'm sending my file to an s3 bucket through the front end, as that seems more efficient from what i've read.
But, for some of my schemas / collections, I will not have the id for which the file / photo is associated -- as they are being created the same time as the upload:
$scope.add = function(){
if($scope.file.photo){
$scope.distiller.photo = 'http://s3.amazonaws.com/whiskey-upload/distillers/'
+ ' needs to be assigned to guid or collection id'
Distillery.create($scope.distiller).then(function(res){
console.log(res);
$scope.distillers.push(res.data.distiller);
var files = $scope.file;
var filename = files.photo.$ngfName;
var type = files.type;
var folder = 'distillers/';
var query = {
files: files,
folder: folder,
filename: res.data.distiller._id,
type: type
};
Uploads.awsUpload(query).then(function(){
$scope.distiller = {};
$scope.file = {};
});
});
}
else{
Distillery.create($scope.distiller).then(function(res){
toastr.success('distillery created without photo');
$scope.distiller = {};
});
}
};
The above code wouldn't work, unless I sent an update on the aws.Upload promise after the distillery object was created and after the file was uploaded to s3.
That doesn't seem efficient.
I could create a guid and assign that to the s3 file name, and also keep a reference of that on the distillery object. This seems hacky, though.
example Guid creator:
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
What would be the cleanest way to achieve what I want?
A good GUID generator is a very standard way to solve a unique id problem. Depending on the algorithm, the chance of a name collision could be close to nil. As you know, JavaScript does not have a native one, so one like yours is reasonable. I don't think its hacky at all.
Here is another by #briguy37:
function generateUUID() {
var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x3|0x8)).toString(16);
});
return uuid; };

Angular HTTP Empty Return

I have a pretty basic Angular Controller:
function PirateController($scope, $http) {
$scope.DetermineBooty = function () {
$scope.Processing = true;
$scope.SavedCount = $scope.PirateCount;
$scope.PirateCount = 'Please wait for Booty...';
$http.get('http://www.Suamere.com/Apps/SCA/API/Booty/' + $scope.SavedCount).
success(function (data) {
if (data != '"0"') {
$scope.ResultText = $scope.SavedCount + ' Pirates found a minimum of ' + data + ' coins.';
$scope.PirateCount = $scope.SavedCount;
} else {
$scope.ResultText = $scope.SavedCount + ' - There is no reason to calculate with that value.';
$scope.PirateCount = "";
}
$scope.Processing = false;
}).
error(function (data) {
$scope.ResultText = $scope.SavedCount + ' - There is no reason to calculate with that value.';
$scope.PirateCount = "";
$scope.Processing = false;
});
};
}
When I publish this to my website, the Error never hits, and that's good. Also, the Success hits and process correctly every time, and that's good.
But when I'm running this on my localhost in VS2013, the error always hits. And the data is always empty.
However, in Fiddler, the result appears to be comming back correctly either on my website or on my localhost. So why, only in my VS2013, is Angular catching empty when the HTTP Return obviously has something in it.
If you are using an absolute URL as shown then when you run on localhost you are making a cross domain request.
Use relative URL's or set the domain using a variable

Can't upload image to remote server using Appcelerator

The application I'm working uses an API developed by another team. I'm working on Titanium 2.1.2 and I'm trying to upload a photo using said API. I'm using Appcelerator's HTTPClient to make the request. Here's my code:
var url = 'http://api.veramiko.com/albums/' + album.veramiko_id + '/photos';
var photo = imageView.toBlob();
var args = { //parameters sent to post photo
file : photo,
description : descriptionText
};
var client = Ti.Network.createHTTPClient({
onload : function(e){
Ti.API.info(this.responseText); //Print the result
},
onerror : function(e){
Ti.API.error(this.responseText); //Print the result
},
timeout : 60000
});
client.open('POST', url);
client.setRequestHeader('Authorization', 'Bearer ' + token);
client.setRequestHeader('Content-type', "multipart/form-data");
client.send(args);
Token is a variable we use to authorize any requests made to the server. I thought that by only converting the image from the ImageView into Blob would be enough to send the photo, but the photo isn't uploaded. The post is created with the description but the photo isn't sent properly.
Do I need to add something else? Is it right to send the photo as a Blob?
EDIT: I read this link and I tried the following with no result:
var url = 'http://api.veramiko.com/albums/' + album.veramiko_id + '/photos';
var boundary = '-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var photo = imageView.toBlob();
var args = {
file : photo,
description : descriptionText.value
};
var contentDisposition = "--" + boundary + "\r\n";
contentDisposition += "Content-Disposition: form-data; name=\"file\";";
contentDisposition += "filename=\"" + imageView.image + "\"\r\n\";";
contentDisposition += "Content-Type: application/octet-stream\r\n\r\n";
var fullContent = contentDisposition + photo + "\r\n--" + boundary + "--";
alert(JSON.stringify(args));
var token = JSON.parse(Ti.App.Properties.getString('loggedUser', 'No existe')).networks[0].token;
var client = Ti.Network.createHTTPClient({
onload : function(e){
Ti.API.info(this.responseText); //Print the result
},
onerror : function(e){
Ti.API.error(this.responseText); //Print the result
},
timeout : 60000
});
client.open('POST', url);
client.setRequestHeader('Authorization', 'Bearer ' + token);
client.setRequestHeader('Content-Type', "multipart/form-data; boundary=\"" + boundary + "\"");
client.setRequestHeader('Connection', 'close');
client.send(fullContent);
I tried to wrap the file with a Content-Disposition and Content-Type header with no result.
I finally found a way to solve this. Please refer to the following link.
This is how my code looked in the end:
// I put the contents of my image into a variable
var f = imageHolder.toImage();
// I create a random name for the image
var tmpName = (new Date()).getTime().toString() + '.png';
// I create a folder where I will store the photo temporally
var g = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'picturesToUpload');
if (!g.exists()) {
// If the directory doesn't exist, make it
g.createDirectory();
};
var photo = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'picturesToUpload', tmpName);
// write the contents of the image into the file
photo.write(f);
// I create my url with the albumId where I'll upload the picture
var url = 'http://api.veramiko.com/albums/' + albumId + '/photos';
var args = {
file : photo.read(), // I read the contents of the file
description : ''
}
var token = JSON.parse(Ti.App.Properties.getString('loggedUser', 'No existe')).networks[0].token;
var client = Ti.Network.createHTTPClient({
onload : function(e){
Ti.API.info('Info received from the uploading: ' + this.responseText);
},
onerror : function(e){
Ti.API.debug('Error: ' + this.responseText);
},
timeout : 60000
});
client.open('POST', url);
// these headers are important
client.setRequestHeader('enctype', 'multipart/form-data');
client.setRequestHeader('Content-Type', 'image/png');
client.setRequestHeader('Authorization', 'Bearer ' + token);
client.send(args);
Hope this info helps more people.
First of all you Clear what is you API Parameter. and where you want to use TOKEN.
var imageView = Ti.UI.createImageView({
backgroundImage : "image.png",
});
var url = 'http://api.veramiko.com/albums/' + album.veramiko_id + '/photos';
var args = { //parameters sent to post photo
file : imageView.backgroundImage,
description : descriptionText,
token : "Token",
};
var client = Ti.Network.createHTTPClient({
onload : function(e){
Ti.API.info(this.responseText); //Print the result
},
onerror : function(e){
Ti.API.error(this.responseText); //Print the result
},
timeout : 60000
});
client.open('POST', url);
client.setRequestHeader("Content-type","multipart/form-data");
client.setRequestHeader("Content-length", args.length);
client.send(args);
Try This, I thought this is working for you...
I found this tutorial, that covers on how to build an uploader.
Titanium Mobile: Build an Image Uploader
You case use this code to upload a file in form-data :
var baseurlAPI = "YOUR API BASEURL HERE";
var file = Ti.Filesystem.getFile(pathToFile);
if(file.exists()){
var xhr = Ti.Network.createHTTPClient({
onload: function(e) {
Ti.API.log('success '+this.responseText);
},
onerror: function(e) {
Ti.API.error(this.responseText);
},
timeout : -1
});
xhr.open('POST', baseurlAPI);
xhr.send({
file: file
});
}else{
console.log('didnt exist ' + file.nativePath);
}

Implementing pagination in backbone

I'm trying to implement a pretty basic pagination & filtering support with backbone
so far now, I have something like this on my Collection.url() function:
url: function() {
var url = 'http://localhost:9000/wines';
var query = '';
if (this.filter) query += '&filter=' + this.filter;
if (this.order) query += '&order=' + this.order;
if (this.page) query += '&page=' + this.page.toString();
if (this.len) query += '&len=' + this.len.toString();
if (query) url += '?' + query.substring(1);
return url;
},
you get the idea
the problem is that when I'm trying to create (POST) or update (PUT) an item, the querystring is also sent to the browser...
is there some way, in the url function, to detect the operation I'm issuing and add the querystring parameters only when fetching (GET) data?
or would you recommend another approach???
I found the following way to do it
I just override the fetch method, like this:
initialize: function(options) {
this._fetch = this.fetch;
this.fetch = function() {
options = {};
options.url = 'http://localhost:9000/wines'
data = {};
if (this.filter) data.filter = this.filter;
if (this.order) data.order = this.order;
if (this.page) data.page = this.page;
if (this.len) data.len = this.len;
options.data = data;
return this._fetch(options);
}
},
I couln't find a way to avoid saving the _fetch variable, I tried with
return Backbone.Collection.fetch(options);
return Backbone.Collection.prototype.fetch(options);
return Wines.fetch(options);
return Wines.prototype.fetch(options);
but none of them seems to work...
--
edit
found it on backbone page:
return Backbone.Collection.prototype.fetch.call(this, options);

Resources