有人能告诉我为什么下面的语句没有将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转换为空字符串。

其他回答

你可以这样设置默认的“Content-Type”:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

关于数据格式:

美元的http。Post和$http。put方法接受任何JavaScript对象(或字符串)值作为其数据参数。如果data是一个JavaScript对象,默认情况下,它将被转换为JSON字符串。

试着使用这种变化

function sendData($scope) {
    $http({
        url: 'request-url',
        method: "POST",
        data: { 'message' : message }
    })
    .then(function(response) {
            // success
    }, 
    function(response) { // optional
            // failed
    });
}

我通过以下代码解决了这个问题:

客户端(Js):

     $http({
                url: me.serverPath,
                method: 'POST',
                data: data,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            }).
                success(function (serverData) {
                    console.log("ServerData:", serverData);
    ......

注意,data是一个对象。

在服务器端(ASP。NET MVC):

[AllowCrossSiteJson]
        public string Api()
        {
            var data = JsonConvert.DeserializeObject<AgentRequest>(Request.Form[0]);
            if (data == null) return "Null Request";
            var bl = Page.Bl = new Core(this);

            return data.methodName;
        }

和'AllowCrossSiteJsonAttribute'需要跨域请求:

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
            base.OnActionExecuting(filterContext);
        }
    }

希望这对你有用。

没有找到如何使用$http的完整代码片段。Post方法将数据发送到服务器,以及为什么在这种情况下它不工作。

以下代码段的解释…

我使用jQuery $。param函数将JSON数据序列化为www post data 在配置变量中设置Content-Type,该变量将随angularJS $http请求一起传递。通知服务器我们将以WWW Post格式发送数据。 注意$ http。post方法,我发送的第一个参数作为url,第二个参数作为数据(序列化)和第三个参数作为配置。

剩下的代码是自己理解的。

$scope.SendData = function () {
           // use $.param jQuery function to serialize data from JSON 
            var data = $.param({
                fName: $scope.firstName,
                lName: $scope.lastName
            });

            var config = {
                headers : {
                    'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
                }
            }

            $http.post('/ServerRequest/PostDataResponse', data, config)
            .success(function (data, status, headers, config) {
                $scope.PostDataResponse = data;
            })
            .error(function (data, status, header, config) {
                $scope.ResponseDetails = "Data: " + data +
                    "<hr />status: " + status +
                    "<hr />headers: " + header +
                    "<hr />config: " + config;
            });
        };

查看$http的代码示例。Post方法在这里。

类似OP建议的工作格式和Denison的回答,除了使用$http。而不是$http,仍然依赖于jQuery。

在这里使用jQuery的好处是可以正确地传递复杂对象;反对手动转换为URL参数,可能会混淆数据。

$http.post( 'request-url', jQuery.param( { 'message': message } ), {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});

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

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

我希望这对你们有帮助