Send formdata using angularjs http service - angularjs

I have to submit user form data. I have done this by using ajaxSubmit but its add one more new JS file into my application. I want to get this done by using angularjs http service. My question is that by using ajaxSubmit I need to send userId id request body and the form data is handle by the ajaxSubmit method itselft. I just want to send the data in a way that ajaxSubmit is doing.
HTML
<form role="form" action="profile_pic">
<div class="cover-50 pull-left pos-relative upload-photo">
<input type="file" onchange="angular.element(this).scope().uploadProfilePic(this)" accept="images/*" capture>
<label>Upload Media</label>
</div>
</form>
Controller
$scope.uploadProfilePic = function(){
$http({
'method': 'POST',
'url': /upload/user/image,
'data': {
'userId' : 457
},
});
// $form.ajaxSubmit({
// type : 'POST',
// url : '/upload/user/image',
// data : {
// 'userId' : 457
// }
// });
}

You could use FormData() to append additional properties to send through $http post.
var data = new FormData();
data.append('userId', 457);
data.append('file', uploadFileUrl);
data.append('abc', "XYZ");
return $http.post('/upload/user/image', data, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).then(function (results) {
//results.data
});

Related

Angularjs $http.post to contact form 7 with content type application/x-www-form-urlencoded

I'm successfully sending POST request from chrome postman plug-in to contact-form-7 and I receive mail and everything.
What I can't figure out is how to send same POST request from angular.
Here's what I have in postman:
POST url: http://example.com/be/home/
REQUEST:
_wpcf7:4
_wpcf7_version:4.7
_wpcf7_locale:en_US
_wpcf7_unit_tag:wpcf7-f4-p6-o1
fname:john
email:admin#example.com
subject:subject
message:message
_wpcf7_is_ajax_call:1
HEADERS:
Content-Type:application/x-www-form-urlencoded
Accept:application/json, text/javascript, */*;q=0.01
BODY(raw):
_wpcf7=4&_wpcf7_version=4.7&_wpcf7_locale=en_US&_wpcf7_unit_tag=wpcf7-f4-p6-o1&fname=john&email=admin#example.com&subject=subject&message=message&_wpcf7_is_ajax_call=1
RESPONSE:
<textarea>{"mailSent":true,"into":"#wpcf7-f4-p6-o1","captcha":null,"message":"Thank you for your message. It has been sent."}</textarea>
Here's what I tried so far:
HomeService:
this.sendMessage = function(successCallback, errorCallback){
$http.post('/be/home', {
headers:{
'Content-Type':'application/x-www-form-urlencoded',
'Accept':'application/json, text/javascript, */*;q=0.01'
},
data:{
'_wpcf7':4,
'_wpcf7_version':4.7,
'_wpcf7_locale':'en_US',
'_wpcf7_unit_tag':'wpcf7-f4-p6-o1',
'fname':'john',
'email':'admin#example.com',
'subject':'subject',
'message':'message',
'_wpcf7_is_ajax_call':1
}
}).then(function(data){
successCallback(data);
}).catch(function(data){
errorCallback(data);
});
}
}
HomeController:
HomeService.sendMessage(function(data){
console.log(data);
}, function(data){
console.log(data);
}
In response I get the whole page, I think I'm sending the headers and data wrong, but I can't figure out how to do it.
EDIT:
{"_wpcf7":4,"_wpcf7_version":4.7,"_wpcf7_locale":"en_US","_w‌​pcf7_unit... This is how REQUEST BODY looks like(JSON) I need it to look like this (form data):
_wpcf7=4&_wpcf7_version=4.7&_wpcf7_locale=en_US&_wpcf7_unit_‌​tag=wpcf7-f4-p6-o1&f‌​name=john&email=admi‌​n%40example.com&subj‌​ect=subject&message=‌​message&_wpcf7_is_aj‌​ax_call=1
And HEADERS: Content-Type:"application/x-www-form-urlencoded"
When I edit request to look like this second example, request passes and email is sent. So question is, is it possible to post Form Data instead of JSON with $http.post?
EDIT:
SOLUTION by #georgeawg
HomeService:
this.sendMessage = function(){
var config = {
//USE serializer
transformRequest: $httpParamSerializer,
headers:{
'Content-Type':'application/x-www-form-urlencoded',
'Accept':'application/json, text/javascript, */*;q=0.01'
}
};
var data = {
'_wpcf7':4,
'_wpcf7_version':4.7,
'_wpcf7_locale':'en_US',
'_wpcf7_unit_tag':'wpcf7-f4-p6-o1',
'fname':'john',
'email':'admin#example.com',
'subject':'subject',
'message':'message',
'_wpcf7_is_ajax_call':1
};
//vvvv RETURN httpPromise
return $http.post('/be/home', data, config);
};
To POST data with content type application/x-www-form-urlencoded, the data needs to be urlencoded. Use the $httpParamSerializer service:
//this.sendMessage = function(successCallback, errorCallback){
this.sendMessage = function(){
var config = {
//USE serializer
transformRequest: $httpParamSerializer,
headers:{
'Content-Type':'application/x-www-form-urlencoded',
'Accept':'application/json, text/javascript, */*;q=0.01'
}
};
var data = {
'_wpcf7':4,
'_wpcf7_version':4.7,
'_wpcf7_locale':'en_US',
'_wpcf7_unit_tag':'wpcf7-f4-p6-o1',
'fname':'john',
'email':'admin#example.com',
'subject':'subject',
'message':'message',
'_wpcf7_is_ajax_call':1
};
//vvvv RETURN httpPromise
return $http.post('/be/home', data, config);
};
The # in the email needs to be percent encoded. The param serializer will do that properly.
Also the is no need to use success and error callbacks as the $http service already returns a promise.
See Why are Callbacks from Promise .then Methods an Anti-Pattern.
In the headers, you specify 'Content-Type':'application/x-www-form-urlencoded' while you provide value in a JSON format in the data property :
data:{
'_wpcf7':4,
'_wpcf7_version':4.7,
'_wpcf7_locale':'en_US',
'_wpcf7_unit_tag':'wpcf7-f4-p6-o1',
'fname':'john',
'email':'admin#example.com',
'subject':'subject',
'message':'message',
'_wpcf7_is_ajax_call':1
}
Either don't specify 'Content-Type':'application/x-www-form-urlencoded' in order to transmit value with the "application/json" content-type that is used by default or else if you really need to use the 'application/x-www-form-urlencoded' Content-Type, provide in the data property a string conform to what 'application/x-www-form-urlencoded' expects to, that is _wpcf7=4&_wpcf7_versio=4.7... .
Try this without adding the headers in request, see this link
HomeService:
this.sendMessage = function(successCallback, errorCallback) {
var data = {
'_wpcf7': 4,
'_wpcf7_version': 4.7,
'_wpcf7_locale': 'en_US',
'_wpcf7_unit_tag': 'wpcf7-f4-p6-o1',
'fname': 'john',
'email': 'admin#example.com',
'subject': 'subject',
'message': 'message',
'_wpcf7_is_ajax_call': 1
}
return $http.post('/be/home', $.param(data));
}
HomeController:
HomeService.sendMessage().then(function(data) {
console.log(data);
});

MissingServletRequestPartException: Required request part 'file' is not present

I've been looking at this but it seems my problem is elsewhere. I am trying to upload a file. The input is currently defined as:
<input
type="file"
style="display: none;"
name="file"
multiple
nv-file-select
uploader="uploader">
This is how the upload is performed:
var uploader = $scope.uploader = new FileUploader({
url: 'http://localhost:8080/rest-api/dl4j/we/uploadModel'
});
uploader.onAfterAddingFile = function($modelFile) {
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
})
.then(
function (data) {
alert("upload success");
},
function (data, status) {
alert("upload error");
}
);
};
Whereas this is the Spring REST endpoint:
#PostMapping(WordEmbeddingApiPaths.UPLOAD_MODEL)
#RequestMapping(method=RequestMethod.POST, headers={"Content-Type=multipart/form-data"})
public ResponseEntity<WordVectorListDto> uploadModel(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
LOGGER.debug("POST uploadModel");
return new ResponseEntity<WordVectorListDto>((WordVectorListDto)null, HttpStatus.OK);
}
The problem is though, that an exception is getting thrown by Spring, telling me that the parameter file is not present:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
This is the request information:
How can I make this file upload work?
I guess it can be related to the content type
In your code i see this:
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
})
So you are defining an undefined content-type; You should set multipart/form-data
Try to put this content-type
I hope it's usefull
Angelo

Model array values are not being submitted by $http service

I defined an array in controller to create a array model. i.e. $scope.campaignPublish[] and I am using in my view template like
<textarea rows="" cols="" name="description" ng-model="campaignPublish['description']"> </textarea>
<input type="text" name="title" ng-model="campaignPublish['title']">
When I submit the form I'm getting all of the form values in this array i.e. $scope.campaignPublish[] but when I'm using $http.post, the data is not being submitted to server. My ajax call is
console.log($scope.campaignPublish); // Getting all form data here
$http.post('url', {'id': campaignId, 'data': $scope.campaignPublish}).then(function (response) {
//$http.post is not submitting the form data on server
});
I read some articles and got to know that it is happening because of http headers. I've already tried each and every solution posted on SO but no one exactly worked. Can anybody tell me where I am doing wrong ?
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': 'text/plain'
},
data: $scope.campaignPublish
}).success(function (reply) {
console.log('sucess');
}).error(function (reply) {
console.log('error');
});

Upload multipart form data with filename in Request Payload

I am still confused about different method of uploading files. The backend server is not under my control but I can upload a file using Swagger page or Postman. That means the server is functioning OK. But when I use AngularJS to do the upload, it doesn't work.
Here is what works using Postman to test. I am just using form-data:
Notice that Request Headers has Content-Type as multipart/form-data. But the Request Payload has filename and Content-Type as image/png.
Here is my code:
$http({
method: 'POST',
url: ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC',
headers: { 'Content-Type': undefined },
transformRequest: function(data) {
var fd = new FormData();
fd.append('file', params.imageData);
return fd;
}
})
params is just an object with file url in imageData.
My code also send similar URL params (so we can ignore that causing issues). But the Request Payload is base64 and it looks different as it is missing the filename field.
I have zero control of the backend and it is written in .NET.
So I guess my question is: Using Angular (either $http or $resource), how do I modify the request so that I am sending the correct Request Payload as how Postman does it? I cannot figure out how to reverse engineer this.
I have tried this https://github.com/danialfarid/ng-file-upload and it actually did OPTIONS request first before POST (assuming CORS issue). But the server gave 405 error for OPTIONS.
You can use something along the line of:
<input type="file" name="file" onchange="uploadFile(this.files)"/>
And in your code:
$scope.uploadFile = function(files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
var uploadUrl = ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC';
$http.post(uploadUrl, fd, {
withCredentials: true,
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).success( ...all right!... ).error( ..damn!... );
};
My need was a follows.
In the form there is a default picture.
Clicking the picture opens a file select window.
When the user selects a file, it is uploaded right away to the server.
As soon as I get a response that the file is valid display the picture to the user instead of the default picture, and add a remove button next to it.
If the user clicks on an existing picture, the file select window reopens.
I tried to use a few code snippets on github that didn't solve the problem, but guided me in the right way, And what I ended up doing is as so:
Directive
angular.module("App").directive('fileModel', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.files = {};
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
// I wanted it to upload on select of file, and display to the user.
element.bind('change', function () {
scope.$apply(function () {
modelSetter(scope, element[0].files[0]);
});
// The function in the controller that uploads the file.
scope.uploadFile();
});
}
};
});
Html
<div class="form-group form-md-line-input">
<!-- A remove button after file has been selected -->
<span class="icon-close pull-right"
ng-if="settings.profile_picture"
ng-click="settings.profile_picture = null"></span>
<!-- Show the picture on the scope or a default picture -->
<label for="file-pic">
<img ng-src="{{ settings.profile_picture || DefaultPic }}"
class="clickable" width="100%">
</label>
<!-- The actual form field for the file -->
<input id="file-pic" type="file" file-model="files.pic" style="display: none;" />
</div>
Controller
$scope.DefaultPic = '/default.png';
$scope.uploadFile = function (event) {
var filename = 'myPic';
var file = $scope.files.pic;
var uploadUrl = "/fileUpload";
file('upfile.php', file, filename).then(function (newfile) {
$scope.settings.profile_picture = newfile.Results;
$scope.files = {};
});
};
function file(q, file, fileName) {
var fd = new FormData();
fd.append('fileToUpload', file);
fd.append('fn', fileName);
fd.append('submit', 'ok');
return $http.post(serviceBase + q, fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).then(function (results) {
return results.data;
});
}
Hope it helps.
P.S. A lot of code was striped from this example, if you need clarification just comment.

change Content-type to "application/json" POST method, RESTful API

I am new at AngularJS and I needed your help.
All I need just need is to POST my json to the API and recieve the proper response.
Here's my JSON where i don't know where to code this.
JSON
{
"userId" :"testAgent2",
"token" :"testAgent2",
"terminalInfo":"test2",
"forceLogin" :"false"
}
NOT SURE IF I'm doing this right.
CONTROLLER.JS
function UserLoginCtrl($scope, UserLoginResource) {
//Save a new userLogin
$scope.loginUser = function() {
var loggedin = false;
var uUsername = $scope.userUsername;
var uPassword = $scope.userPassword;
var uforcelogin = 'true';
UserLoginResource.save();
}
}
SERVICES.JS
angular.module('UserLoginModule', ['ngResource'])
.factory('UserLoginResource', function($resource, $http) {
$http.defaults.useXDomain = true;
delete $http.defaults.headers.common['X-Requested-With'];
$http.defaults.headers.post["Content-Type"] = "application/json"; //NOT WORKING
return $resource('http://123.123.123.123\\:1234/SOME/LOCATION/THERE', {}, {
save: {
method:'POST',
headers: [{'Content-Type': 'application/json'}]
} //NOT WORKING EITHER
});
});
INDEX.HTML
<html ng-app>
<head>
<script src="js/lib/angular/angular.js"></script>
<script src="js/lib/angular/angular-resource.js"></script>
</head>
<body ng-controller="UserLoginCtrl">
<form class="form-horizontal" name="form-horizontal" ng-submit="loginUser();">
<div class="button-login">
<!-- start: button-login -->
<button class="btn btn-primary" type="submit">Login</button>
</div>
</form>
</body>
</html>
I kept on getting a response like Unsupported Media Type. I don't know, what else to do.
Assuming you are able to use one of the more recent "unstable" releases, the correct syntax to change the header is.
app.factory('BarService', function ($resource) {
var BarService = $resource('/foo/api/bars/:id', {}, {
'delete': {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
}
});
return BarService;
});
I find the $resource service is a tremendously powerful tool for building applications and has matured to a point that you do not need to fall back to $http as much. Plus its active record like patterns are damn convenient.
Posting a JSON object is quite easy in Angular. All you need to do is the following:
Create a Javascript Object
I'll use your exact properties from your code.
var postObject = new Object();
postObject.userId = "testAgent2";
postObject.token = "testAgent2";
postObject.terminalInfo = "test2";
postObject.forceLogin = "false";
Post the object to the API
To post an object to an API you merely need a simple $http.post function. See below:
$http.post("/path/to/api/", postObject).success(function(data){
//Callback function here.
//"data" is the response from the server.
});
Since JSON is the default method of posting to an API, there's no need to reset that. See this link on $http shortcuts for more information.
With regards to your code specifically, try changing your save method to include this simple post method.
The right way to set 'Content-Type': 'application/json' is setting a transformRequest function for the save action.
angular.module('NoteWrangler')
.factory('NoteNgResource', function NoteNgResourceFactory($resource) {
// https://docs.angularjs.org/api/ngResource/service/$resource
return $resource("./php/notes/:id", {}, {
save : { // redefine save action defaults
method : 'POST',
url : "./php/notes", // I dont want the id in the url
transformRequest: function(data, headers){
console.log(headers);
headers = angular.extend({}, headers, {'Content-Type': 'application/json'});
console.log(headers);
console.log(data);
console.log(angular.toJson(data));
return angular.toJson(data); // this will go in the body request
}
}
});
});
It seems there isn't a method to clear query parameters, the request will have both...

Resources