117

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

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

requestData只是一个带有一些基本字符串属性的 javascript 对象。

我正在将我们的东西转移到使用 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 是否为此提供了开箱即用的东西。

4

13 回答 13

140

我认为paramsconfig 参数在这里不起作用,因为它将字符串添加到 url 而不是 body 但是添加到 Infeligo 建议的内容是默认转换的全局覆盖的示例(使用 jQuery参数作为示例进行转换参数字符串的数据)。

设置全局 transformRequest 函数:

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
    });
于 2012-08-30T07:07:28.097 回答
22

如果使用Angular >= 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'
  }
});

并且它将正确地将数据序列化并使用Content-Type 标头param1=value1&param2=value2将其发送到,正如端点上的 POST 请求通常所期望的那样。/requesturlapplication/x-www-form-urlencoded; charset=utf-8

于 2016-05-18T09:50:01.500 回答
17

来自 AngularJS 文档:

params – {Object.} – 字符串或对象的映射,将在 url 之后转换为 ?key1=value1&key2=value2。如果值不是字符串,它将被 JSON 化。

因此,提供字符串作为参数。如果您不希望那样,请使用转换。同样,从文档中:

要在本地覆盖这些转换,请将转换函数指定为配置对象的 transformRequest 和/或 transformResponse 属性。要全局覆盖默认转换,请覆盖 $httpProvider 的 $httpProvider.defaults.transformRequest 和 $httpProvider.defaults.transformResponse 属性。

有关更多详细信息,请参阅文档

于 2012-08-30T06:36:58.370 回答
15

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

于 2013-04-23T17:27:34.027 回答
7

请注意,从 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
});
于 2015-12-23T19:31:31.677 回答
5

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

要使其正常工作,您必须通过执行此操作来覆盖现有的标头

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 天时间才弄清楚这一点。

于 2013-05-02T04:25:18.393 回答
5

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

$_POST = json_decode(file_get_contents('php://input'), true);
于 2013-11-13T13:41:35.610 回答
4

修改默认标题:

$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);
于 2014-11-30T19:58:07.610 回答
3
   .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 () {});
    }
  ]);
于 2016-05-04T10:01:48.670 回答
2

快速调整 - 对于那些对 transformRequest 函数的全局配置有问题的人,这是我用来消除Cannot read property 'jquery' of undefined错误的代码段:

$httpProvider.defaults.transformRequest = function(data) {
        return data != undefined ? $.param(data) : null;
    }
于 2013-01-21T00:43:19.367 回答
1

您也可以在不更改服务器中的代码、更改$http.post调用中的标头并使用$_POST常规方式的情况下解决此问题。在这里解释:http: //victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

于 2015-02-12T01:17:19.420 回答
0

我发现很多次有问题的行为。我从 express(没有类型)和 bodyParser(使用 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在客户端的请求字符串中给出内容类型也很重要。

于 2016-09-02T14:39:39.887 回答
0

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
                    }
            );
于 2018-06-28T18:54:31.667 回答