AngularJS – 任何方式为$ http.post发送请求参数,而不是JSON?
我有一些旧的代码,通过jQuery的post方法发出AJAX POST请求,看起来像这样:
$.post("/foo/bar", requestData, function(responseData) { //do stuff with response }
requestData
只是一个具有一些基本string属性的JavaScript对象。
我正在把我们的东西转移到使用Angular的过程中,我想用$ http.postreplace这个调用。 我想出了以下几点:
$http.post("/foo/bar", requestData).success( function(responseData) { //do stuff with response } });
当我这样做,我得到了从服务器的500错误响应。 使用Firebug,我发现这样发送请求体:
{"param1":"value1","param2":"value2","param3":"value3"}
成功的jQuery $.post
像这样发送主体:
param1=value1¶m2=value2¶m3=value3
我正在打的端点是期望的请求参数,而不是JSON。 所以,我的问题是有无论如何告诉$http.post
发送JavaScript对象作为请求参数,而不是JSON? 是的,我知道我可以从对象中自己构buildstring,但是我想知道Angular是否提供了任何开箱即用的function。
我认为params
configuration参数在这里不起作用,因为它将string添加到url而不是body中,但是添加到Infeligo在这里提出的是一个默认转换的全局覆盖的例子(以jQuery param为例将数据转换为参数string)。
设置全局变换请求函数:
var app = angular.module('myApp'); app.config(function ($httpProvider) { $httpProvider.defaults.transformRequest = function(data){ if (data === undefined) { return data; } return $.param(data); } });
这样,所有对$ http.post的调用都会自动将主体转换为jQuery $.post
调用所使用的相同参数格式。
请注意,您可能还需要设置每个呼叫的Content-Type标题或全局像这样的:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
每次调用的非全局transformRequest示例:
var transform = function(data){ return $.param(data); } $http.post("/foo/bar", requestData, { headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, transformRequest: transform }).success(function(responseData) { //do stuff with response });
如果使用Angular> = 1.4 ,这里是我发现的最干净的解决scheme,不依赖于任何自定义或外部:
angular.module('yourModule') .config(function ($httpProvider, $httpParamSerializerJQLikeProvider){ $httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get()); $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; });
然后你可以在你的应用程序的任何地方做这个:
$http({ method: 'POST', url: '/requesturl', data: { param1: 'value1', param2: 'value2' } });
它会正确地将数据序列化为param1=value1¶m2=value2
并通过application/x-www-form-urlencoded; charset=utf-8
发送到/requesturl
application/x-www-form-urlencoded; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Content-Type头,因为通常在端点上使用POST请求。
从AngularJS文档:
params – {Object。} – string或对象的映射将被转换为?key1 = value1&key2 = value2之后的url。 如果该值不是一个string ,它将被JSON化。
所以,提供string作为参数。 如果你不想要,那么使用转换。 再次,从文档:
要在本地覆盖这些转换,请将转换函数指定为configuration对象的transformRequest和/或transformResponse属性。 要全局覆盖默认转换,请覆盖$ httpProvider的$ httpProvider.defaults.transformRequest和$ httpProvider.defaults.transformResponse属性。
请参阅文档了解更多细节。
使用jQuery的$.param
函数来序列化requestData中的JSON数据。
总之,使用类似的代码作为你的:
$http.post("/foo/bar", $.param(requestData), { headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } } ).success( function(responseData) { //do stuff with response } });
为了使用这个,你必须在你的页面中包含jQuery和AngularJS。
请注意,从Angular 1.4开始,您可以在不使用jQuery的情况下序列化表单数据。
在app.js中:
module.run(function($http, $httpParamSerializerJQLike) { $http.defaults.transformRequest.unshift($httpParamSerializerJQLike); });
然后在你的控制器中:
$http({ method: 'POST', url: myUrl', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, data: myData });
这可能有点破解,但我避免了这个问题,并将json转换为服务器端的PHP POST数组:
$_POST = json_decode(file_get_contents('php://input'), true);
我也有设置自定义http身份validation的问题,因为$资源caching请求。
要做到这一点,你必须重写现有的标题
var transformRequest = function(data, headersGetter){ var headers = headersGetter(); headers['Authorization'] = 'WSSE profile="UsernameToken"'; headers['X-WSSE'] = 'UsernameToken ' + nonce headers['Content-Type'] = 'application/json'; }; return $resource( url, { }, { query: { method: 'POST', url: apiURL + '/profile', transformRequest: transformRequest, params: {userId: '@userId'} }, } );
我希望我能帮助别人。 我花了三天的时间来弄清楚这一点。
修改默认标题:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
然后使用JQuery的$.param
方法:
var payload = $.param({key: value}); $http.post(targetURL, payload);
.controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) { var data = { TimeStamp : "2016-04-25 12:50:00" }; $http({ method: 'POST', url: 'serverutilizationreport', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, data: $httpParamSerializerJQLike(data), }).success(function () {}); } ]);
快速调整 – 对于那些遇到transformRequest函数的全局configuration有问题的人,这里是我用来摆脱Cannot read property 'jquery' of undefined
错误的Cannot read property 'jquery' of undefined
的代码片段:
$httpProvider.defaults.transformRequest = function(data) { return data != undefined ? $.param(data) : null; }
你也可以在不改变服务器代码的情况下解决这个问题,在$http.post
调用中改变头文件,并以常规的方式使用$_POST
。 在这里解释: http : //victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
我发现这个整体有许多次有问题的行为。 我用express(没有types)和bodyParser(用dt〜body-parsertypes)。
我没有尝试上传一个文件,而是简单地解释一个后置string中给出的JSON。
request.body
只是一个空的json( {}
)。
经过很多调查终于这对我工作:
import { json } from 'body-parser'; ... app.use(json()); <-- should be defined before the first POST handler!
从客户端提供请求string中的application/json
内容types也是很重要的。