AngularJS-有什么方法可以让 $http.post 代替 JSON 发送请求参数吗?

我有一些旧的代码,它通过 JQuery 的 post 方法发出一个 AJAX POST 请求,看起来像这样:

$.post("/foo/bar", requestData,
function(responseData)
{
//do stuff with response
}

requestData is just a javascript object with some basic string properties.

我正在把我们的东西移到 Angular 上,我想用 $http.post 代替这个调用。我想到了以下几点:

$http.post("/foo/bar", requestData).success(
function(responseData) {
//do stuff with response
}
});

当我这样做时,我从服务器得到了500个错误响应。通过使用 Firebug,我发现这样发送请求主体:

{"param1":"value1","param2":"value2","param3":"value3"}

成功的 jQuery $.post发送主体如下:

param1=value1&param2=value2&param3=value3

我要访问的端点需要的是请求参数,而不是 JSON。因此,我的问题是,是否有办法告诉 $http.post将 javascript 对象作为请求参数而不是 JSON 发送出去?是的,我知道我可以从对象自己构造字符串,但我想知道 Angular 是否提供了现成的东西。

215208 次浏览

来自 AngularJS 文档:

params – {Object.} – Map of strings or objects which 将在 url 之后转换为? key1 = value1 & key2 = value2 Value 不是字符串 ,它将被 JSONfied。

因此,提供字符串作为参数。如果你不想这样做,那么就使用转换:

若要在本地重写这些转换,请指定转换函数 作为配置的 formRequest 和/或 formResponse 属性 若要全局重写默认转换,请重写 $httpProvider.defaults.formRequest 和 元素的响应属性 $httpProvider.

详情请参阅 文件

I think the params config parameter won't work here since it adds the string to the url instead of the body but to add to what Infeligo suggested here is an example of the global override of a default transform (using jQuery Param as an example to convert the data to 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';

每次呼叫的非全局转换请求示例:

    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
});

Quick adjustment - for those of you having trouble with the global configuration of the transformRequest function, here's the snippet i'm using to get rid of the Cannot read property 'jquery' of undefined error:

$httpProvider.defaults.transformRequest = function(data) {
return data != undefined ? $.param(data) : null;
}

使用 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。

我在设置自定义 http 身份验证方面也有问题,因为 $resource 缓存了请求。

To make it work you have to overwrite the existing headers by doing this

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'}
},
}
);

我希望我能够帮助别人。我花了3天的时间才弄明白这个问题。

这可能有点麻烦,但我避免了这个问题,并在服务器端将 json 转换为 PHP 的 POST 数组:

$_POST = json_decode(file_get_contents('php://input'), true);

修改默认标题:

$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);

您也可以解决这个问题而不改变服务器中的代码,改变头在 $http.post调用和使用 $_POST的常规方式。这里解释: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

Note that as of Angular 1.4, you can serialize the form data without using jQuery.

In the app.js:

module.run(function($http, $httpParamSerializerJQLike) {
$http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});

Then in your controller:

$http({
method: 'POST',
url: myUrl',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: myData
});
   .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 () {});
}
]);

如果使用 角度 > = 1.4,这是我发现的最干净的解决方案,不依赖任何自定义或外部:

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&param2=value2,并使用 application/x-www-form-urlencoded; charset=utf-8 Content-Type 头将数据发送到 /requesturl,就像通常在端点上发送 POST 请求时所期望的那样。

我发现这个整体的许多问题行为。我在 Express (不包含类型)和 body Parser (包含 dt ~ body-parser 类型)中使用了它。

我没有尝试上传文件,而只是简单地解释文章字符串中给出的 JSON。

request.body只是一个空 json ({})。

经过大量的调查,我终于明白了:

import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!

从客户端给出请求字符串中的 application/json内容类型也很重要。

AngularJS v1.4.8 + (v1.5.0)的语法

       $http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);

例如:

    var url = "http://example.com";


var data = {
"param1": "value1",
"param2": "value2",
"param3": "value3"
};


var config = {
headers: {
'Content-Type': "application/json"
}
};


$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);