首页 文章

AngularJS - $ http.post发送请求参数而不是JSON的任何方式?

提问于
浏览
115

我有一些旧代码通过jQuery's post method发出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

我遇到的 endpoints 是期望请求参数而不是JSON . 所以,我的问题是,无论如何要告诉 $http.post 将javascript对象作为请求参数而不是JSON发送?是的,我知道我可以自己从对象构造字符串,但我想知道Angular是否提供了开箱即用的东西 .

13 回答

  • 1

    我认为 params config参数在这里不起作用,因为它将字符串添加到url而不是body,但是添加到Infeligo建议的是一个默认变换的全局覆盖的示例(使用jQuery param作为示例)将数据转换为param字符串) .

    Set up global transformRequest function:

    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 调用所使用的相同param格式 .

    请注意,您可能还希望为每个调用设置Content-Type标头,或者像这样全局设置:

    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
    

    Sample non-global transformRequest per call:

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

    如果使用 Angular >= 1.4 ,这里's the cleanest solution I' ve发现不依赖于任何自定义或外部:

    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 ,因为它通常是 endpoints 上的POST请求所期望的 .

  • 0

    来自AngularJS文档:

    params - {Object . } - 在url之后将转向的字符串或对象的映射?key1 = value1&key2 = value2 . 如果该值不是字符串,则它将是JSONified .

    因此,提供字符串作为参数 . 如果您不想这样,那么使用转换 . 再次,从文档:

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

    有关详细信息,请参阅documentation .

  • 7

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

  • 15

    请注意,从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
    });
    
  • 5

    这可能是一个黑客,但我避免了这个问题,并将json转换为服务器端的PHP的POST数组:

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

    我也有设置自定义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天时间才想出这个 .

  • 140

    修改默认标头:

    $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);
    
  • 5
    .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 () {});
        }
      ]);
    
  • 17

    快速调整 - 对于那些遇到transformRequest函数全局配置问题的人,这里使用's the snippet i' m来摆脱 Cannot read property 'jquery' of undefined 错误:

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

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

  • 0

    我发现很多次这个问题的行为 . 我从express(没有打字)和bodyParser(使用dt~body-parser typings)中使用它 .

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

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

    经过大量调查后,这对我有用:

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

    从客户端向请求字符串中提供 application/json 内容类型也很重要 .

  • 20

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

相关问题