有人能告诉我为什么下面的语句没有将post数据发送到指定的url吗?url被调用,但在服务器上,当我打印$_POST -我得到一个空数组。如果我在控制台中打印消息,然后将其添加到数据-它显示了正确的内容。

$http.post('request-url',  { 'message' : message });

我也尝试过将数据作为字符串(具有相同的结果):

$http.post('request-url',  "message=" + message);

当我以以下格式使用它时,它似乎正在工作:

$http({
    method: 'POST',
    url: 'request-url',
    data: "message=" + message,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});

但是是否有一种方法可以用$http.post() -我总是必须包括头以便它工作吗?我相信上面的内容类型是指定发送数据的格式,但我可以把它作为javascript对象发送吗?


当前回答

我一直在使用公认的答案的代码(Felipe的代码)一段时间,它工作得很好(谢谢,Felipe!)。

但是,最近我发现它有空对象或数组的问题。 例如,当提交这个对象时:

{
    A: 1,
    B: {
        a: [ ],
    },
    C: [ ],
    D: "2"
}

PHP似乎根本看不到B和C。结果是这样的:

[
    "A" => "1",
    "B" => "2"
]

看看实际的请求在Chrome显示:

A: 1
:
D: 2

我写了一个替代代码片段。它似乎在我的用例中工作得很好,但我还没有对它进行广泛测试,所以请谨慎使用。

我使用TypeScript,因为我喜欢强类型,但它很容易转换为纯JS:

angular.module("MyModule").config([ "$httpProvider", function($httpProvider: ng.IHttpProvider) {
    // Use x-www-form-urlencoded Content-Type
    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";

    function phpize(obj: Object | any[], depth: number = 1): string[] {
        var arr: string[] = [ ];
        angular.forEach(obj, (value: any, key: string) => {
            if (angular.isObject(value) || angular.isArray(value)) {
                var arrInner: string[] = phpize(value, depth + 1);
                var tmpKey: string;
                var encodedKey = encodeURIComponent(key);
                if (depth == 1) tmpKey = encodedKey;
                else tmpKey = `[${encodedKey}]`;
                if (arrInner.length == 0) {
                    arr.push(`${tmpKey}=`);
                }
                else {
                    arr = arr.concat(arrInner.map(inner => `${tmpKey}${inner}`));
                }
            }
            else {
                var encodedKey = encodeURIComponent(key);
                var encodedValue;
                if (angular.isUndefined(value) || value === null) encodedValue = "";
                else encodedValue = encodeURIComponent(value);

                if (depth == 1) {
                    arr.push(`${encodedKey}=${encodedValue}`);
                }
                else {
                    arr.push(`[${encodedKey}]=${encodedValue}`);
                }
            }
        });
        return arr;
    }

    // Override $http service's default transformRequest
    (<any>$httpProvider.defaults).transformRequest = [ function(data: any) {
        if (!angular.isObject(data) || data.toString() == "[object File]") return data;
        return phpize(data).join("&");
    } ];
} ]);

它的效率比Felipe的代码低,但我认为这无关紧要,因为与HTTP请求本身的整体开销相比,它应该是即时的。

现在PHP显示:

[
    "A" => "1",
    "B" => [
        "a" => ""
    ],
    "C" => "",
    "D" => "2"
]

据我所知,让PHP识别B.a和C是空数组是不可能的,但至少键会出现,当代码依赖于某个结构时,这很重要,即使它内部实际上是空的。

还要注意,它将未定义的和null转换为空字符串。

其他回答

我在使用asp.net MVC时遇到了同样的问题,在这里找到了解决方案

刚接触AngularJS的人有很多困惑,为什么 $http服务简写函数($http.post()等)不会出现 可切换与jQuery的等价物(jQuery.post()等) 不同之处在于jQuery和AngularJS如何序列化和传输数据。从根本上说,问题在于你所选择的服务器语言无法理解AngularJS的传输…jQuery默认使用

Content-Type: x-www-form-urlencoded

以及熟悉的foo=bar&baz=moe序列化。

AngularJS使用

Content-Type: application/json 

{"foo": "bar", "baz": "moe"}

JSON序列化,不幸的是一些Web服务器语言—特别是 php—不要本地反序列化。

效果非常好。

CODE

// Your app's root module...
angular.module('MyModule', [], function($httpProvider) {
  // Use x-www-form-urlencoded Content-Type
  $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
 
  /**
   * The workhorse; converts an object to x-www-form-urlencoded serialization.
   * @param {Object} obj
   * @return {String}
   */ 
  var param = function(obj) {
    var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
      
    for(name in obj) {
      value = obj[name];
        
      if(value instanceof Array) {
        for(i=0; i<value.length; ++i) {
          subValue = value[i];
          fullSubName = name + '[' + i + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value instanceof Object) {
        for(subName in value) {
          subValue = value[subName];
          fullSubName = name + '[' + subName + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value !== undefined && value !== null)
        query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
    }
      
    return query.length ? query.substr(0, query.length - 1) : query;
  };
 
  // Override $http service's default transformRequest
  $httpProvider.defaults.transformRequest = [function(data) {
    return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
  }];
});

与JQuery不同,出于学究的考虑,Angular使用JSON格式进行POST 数据从客户端传输到服务器端(JQuery应用x-www-form-urlencoded,尽管JQuery和Angular使用JSON进行数据输入)。因此有两个部分的问题:在js客户端部分和在你的服务器部分。所以你需要:

把js的Angular客户端部分像这样放: http({美元 方法:“文章”, url:“请求url”, data: {'message': 'Hello world'} });

AND

写入服务器部分以接收来自客户端的数据(如果是php)。 $data = file_get_contents("php://input"); $ datasondecode = json_decode($data); $message = $dataJsonDecode->消息; echo $消息;/ /“Hello world”

注意:$_POST将不起作用!

希望这个方法对我有用,对你也有用。

用这种方法。没必要写这么多

 isAuth = $http.post("Yr URL", {username: username, password: password});

在nodejs的后端

app.post("Yr URL",function(req,resp)
{

  var username = req.body.username||req.param('username');
  var password = req.body.password||req.param('password');
}

我希望这对你们有帮助

通过使用非常简单的方法,我们可以这样做:

 $http({
        url : "submit_form_adv.php",
        method : 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function(obj) {
            var str = [];
            for(var p in obj)
                str.push(encodeURIComponent(p)+' = '+encodeURIComponent(obj[p]));

            return str.join('&');
        },
        data : {sample_id : 100, sample_name: 'Abin John'},

    }).success(function(data, status, headers, config) {

    }).error(function(ata, status, headers, config) {

    });

这可能是一个很晚的答案,但我认为最合适的方法是使用angular在使用$httpParamSerializer执行“get”请求时使用的同一段代码,它将不得不注入到你的控制器中 所以你可以简单地做下面的事情,而不需要使用Jquery, 美元http.post (url, httpParamSerializer美元({参数:val}))

app.controller('ctrl',function($scope,$http,$httpParamSerializer){
    $http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}