AngularJs $http.post() не отправляет данные

может ли кто-нибудь сказать мне, почему следующее заявление не отправляет данные 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?

30 ответов


Я имел такую же проблему с помощью asp.net MVC и нашел решение здесь

есть много путаницы среди новичков AngularJS а почему $http сервис стенография функции ($http.post(), etc.) не представляется быть замены с jQuery эквиваленты (jQuery.post(), etc.)

разница в том, как jQuery и AngularJS сериализация и передача данных. В принципе, проблема заключается в том, что ваш серверный язык выбора не может понять передачу AngularJS изначально ... По умолчанию jQuery передает данные с использованием

Content-Type: x-www-form-urlencoded

и знакомый foo=bar&baz=moe сериализация.

AngularJS, однако, передает данные с помощью

Content-Type: application/json 

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

сериализация JSON, которая, к сожалению, некоторые языки веб-сервера -в частности, В PHP - не unserialize изначально.

работает как шарм.

код

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

это не очень ясно выше, но если вы получаете запрос в PHP, вы можете использовать:

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

для доступа к массиву в PHP из сообщения AngularJS.


вы можете установить по умолчанию "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
    });
}

У меня была аналогичная проблема, и мне интересно, может ли это быть полезно: https://stackoverflow.com/a/11443066

var xsrf = $.param({fkey: "key"});
$http({
    method: 'POST',
    url: url,
    data: xsrf,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

С уважением,


Мне нравится использовать функцию для преобразования объектов в post params.

myobject = {'one':'1','two':'2','three':'3'}

Object.toparams = function ObjecttoParams(obj) {
    var p = [];
    for (var key in obj) {
        p.push(key + '=' + encodeURIComponent(obj[key]));
    }
    return p.join('&');
};

$http({
    method: 'POST',
    url: url,
    data: Object.toparams(myobject),
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

это, наконец, было рассмотрено в angular 1.4 с помощью $httpParamSerializerJQLike

см.https://github.com/angular/angular.js/issues/6039

.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
  method: 'POST',
  url: baseUrl,
  data: $httpParamSerializerJQLike({
    "user":{
      "email":"wahxxx@gmail.com",
      "password":"123456"
    }
  }),
  headers:
    'Content-Type': 'application/x-www-form-urlencoded'
})})

я использую jQuery param С AngularJS сообщение requrest. Вот пример ... создайте модуль приложения AngularJS, где myapp определен с ng-app в вашем HTML-коде.

var app = angular.module('myapp', []);

теперь давайте создадим контроллер входа в систему и опубликуем электронную почту и пароль.

app.controller('LoginController', ['$scope', '$http', function ($scope, $http) {
    // default post header
    $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
    // send login data
    $http({
        method: 'POST',
        url: 'https://example.com/user/login',
        data: $.param({
            email: $scope.email,
            password: $scope.password
        }),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    }).success(function (data, status, headers, config) {
        // handle success things
    }).error(function (data, status, headers, config) {
        // handle error things
    });
}]);

Я не люблю объяснять код, это достаточно просто понять:) обратите внимание, что param из jQuery, поэтому вы должны установить jQuery и AngularJS, чтобы сделать это рабочий. Вот скриншот.

enter image description here

надеюсь, это полезно. Спасибо!


у меня была такая же проблема с AngularJS и Node.JS + Express 4 + маршрутизатор

маршрутизатор ожидает данные от запроса post в теле. Это тело всегда было пустым, если я следовал примеру из Angular Docs

нотация 1

$http.post('/someUrl', {msg:'hello word!'})

но если я использовал его в данные

нотация 2

$http({
       withCredentials: false,
       method: 'post',
       url: yourUrl,
       headers: {'Content-Type': 'application/x-www-form-urlencoded'},
       data: postData
 });

Edit 1:

иного узла.маршрутизатор js будет ожидать данные в req.тело, если используется обозначение 1:

req.body.msg

что также отправляет информацию как полезную нагрузку JSON. Это лучше в некоторых случаях, когда у вас есть массивы в вашем json и x-www-form-urlencoded даст некоторые проблемы.

это сработало. Надеюсь, это поможет.


В отличие от JQuery и ради педантичности, Angular использует формат JSON для POST данные передачи от клиента к серверу (jQuery применяет x-www-form-urlencoded предположительно, хотя JQuery и Angular используют JSON для вменения данных). Поэтому есть две части проблемы: в клиентской части js и в вашей серверной части. Нужно так:

  1. положите часть клиента js угловую как это:

    $http({
    method: 'POST',
    url: 'request-url',
    data: {'message': 'Hello world'}
    });
    

и

  1. напишите в серверной части, чтобы получить данные от клиента (если это php).

            $data               = file_get_contents("php://input");
            $dataJsonDecode     = json_decode($data);
            $message            = $dataJsonDecode->message;
            echo $message;     //'Hello world'
    

Примечание: $_POST не будет работать!

решение работает для меня, надеюсь, и для вас.


для отправки данных через Post methode с $http из angularjs вам нужно изменить

data: "message=" + message С data: $.param({message:message})


чтобы основываться на ответе @felipe-miosso:

  1. загрузите его как модуль AngularJS из здесь,
  2. установки
  3. добавьте его в свое приложение:

    var app = angular.module('my_app', [ ... , 'httpPostFix']);
    

у меня нет репутации для комментариев, но в ответ / дополнение к ответу Дона Ф:

$params = json_decode(file_get_contents('php://input'));

второй параметр true необходимо добавить в json_decode функция для правильного возврата ассоциативного массива:

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


Угловое

  var payload = $.param({ jobId: 2 });

                this.$http({
                    method: 'POST',
                    url: 'web/api/ResourceAction/processfile',
                    data: payload,
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
                });

веб-API 2

public class AcceptJobParams
        {
            public int jobId { get; set; }
        }

        public IHttpActionResult ProcessFile([FromBody]AcceptJobParams thing)
        {
            // do something with fileName parameter

            return Ok();
        }

этот код решил проблему для меня. Это решение на уровне приложения:

moduleName.config(['$httpProvider',
  function($httpProvider) {
    $httpProvider.defaults.transformRequest.push(function(data) {
        var requestStr;
        if (data) {
            data = JSON.parse(data);
            for (var key in data) {
                if (requestStr) {
                    requestStr += "&" + key + "=" + data[key];
                } else {
                    requestStr = key + "=" + data[key];
                }
            }
        }
        return requestStr;
    });
    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
  }
]);

добавьте это в свой JS-файл:

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

и добавьте это в ваш файл-сервера:

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

это должно сработать.


Я тоже столкнулся с подобной проблемой и я делал что-то подобное, и это не сработало. Мой контроллер Spring не смог прочитать параметр данных.

var paramsVal={data:'"id":"1"'};
  $http.post("Request URL",  {params: paramsVal});  

но, читая этот форум и API Doc, я попытался следовать пути, и это сработало для меня. Если у кого-то также есть аналогичная проблема, вы можете попробовать ниже.

$http({
      method: 'POST',
      url: "Request URL",           
      params: paramsVal,
      headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
            });

пожалуйста, проверьте https://docs.angularjs.org/api/ng/service/$http#post для того, что делает param config. {data: '"id":" 1"'} - карта строки или объекты, которые будут включены в URL?data= "id:1"


Это, вероятно, поздний ответ, но я думаю, что наиболее правильным способом является использование того же фрагмента кода углового использования при выполнении запроса "get", используя вас $httpParamSerializer придется ввести его в контроллер таким образом, вы можете просто сделать следующее, не используя Jquery вообще , $http.post(url,$httpParamSerializer({param:val}))

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

в моем случае я решаю проблему так :

var deferred = $q.defer();

$http({
    method: 'POST',
    url: 'myUri', 
    data: $.param({ param1: 'blablabla', param2: JSON.stringify(objJSON) }),
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(
    function(res) {
        console.log('succes !', res.data);
        deferred.resolve(res.data);
    },
    function(err) {
        console.log('error...', err);
        deferred.resolve(err);
    }
);
return deferred.promise;

вам нужно использовать JSON.stringify для каждого параметра, содержащего объект JSON, а затем создайте объект данных с помощью"$.param": -)

NB: мой "objJSON" - это объект JSON, содержащий массив, целое число, строку и содержимое html. Его общий размер составляет >3500 символов.


Я знаю принят ответ. Но, может помочь будущим читателям, если ответ их не устраивает по какой-либо причине.

Angular не делает ajax так же, как jQuery. Пока я пытался следовать руководству по изменению angular $httpprovider , я столкнулся с другими проблемами. Например. Я использую codeigniter, в котором $this->input->is_ajax_request() функция всегда терпела неудачу (которая была написана другим программистом и использовалась глобально, поэтому не может измениться), говоря, что это не настоящий ajax запрос.

чтобы решить эту проблему, я принял помощь отложенное обещание. Я тестировал его в Firefox, и ie9, и он работал.

у меня есть следующая функция, определенная за пределами любой угловой код. Эта функция делает регулярный вызов jQuery ajax и возвращает отложенный / обещанный (я все еще учусь) объект.

function getjQueryAjax(url, obj){
    return $.ajax({
        type: 'post',
        url: url,
        cache: true,
        data: obj
    });
}

тогда я называю его угловым кодом, используя следующий код. Обратите внимание, что мы должны обновить $scope вручную с помощью $scope.$apply() .

    var data = {
        media: "video",
        scope: "movies"
    };
    var rPromise = getjQueryAjax("myController/getMeTypes" , data);
    rPromise.success(function(response){
        console.log(response);
        $scope.$apply(function(){
            $scope.testData = JSON.parse(response);
            console.log($scope.testData);
        });
    }).error(function(){
        console.log("AJAX failed!");
    });

это может быть не идеальный ответ, но это позволило мне использовать вызовы jQuery ajax с angular и позволило мне обновить $scope.


У меня была та же проблема в express .. для решения вам нужно использовать bodyparser для анализа объектов json перед отправкой http-запросов ..

app.use(bodyParser.json());

Я использую asp.net веб-службы WCF с угловым JS и ниже кодом работал:

 $http({
        contentType: "application/json; charset=utf-8",//required
        method: "POST",
        url: '../../operation/Service.svc/user_forget',
        dataType: "json",//optional
        data:{ "uid_or_phone": $scope.forgettel, "user_email": $scope.forgetemail },
        async: "isAsync"//optional

       }).success( function (response) {

         $scope.userforgeterror = response.d;                    
       })

надеюсь, что это помогает.


не нашел полный фрагмент кода о том, как использовать $http.метод POST для отправки данных на сервер и почему он не работает в этом случае.

пояснения ниже фрагмента кода...

  1. Я использую jQuery $.функция param для сериализации данных JSON в WWW post data
  2. установка типа содержимого в переменной config, которая будет передана вместе с запросом angularJS $http.сообщение, которое указывает серверу, что мы отправляем данные в формат сообщения www.

  3. обратите внимание на $htttp.метод post, где я отправляю 1-й параметр как url, 2-й параметр как данные (сериализованные) и 3-й параметр как config.

оставшийся код понятен.

$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 здесь.


Если вы используете PHP, это простой способ получить доступ к массиву в PHP из сообщения AngularJS.

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

при использовании угловые >= 1.4, вот самое чистое решение с использованием сериализатор, предоставляемый Angular:

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 и отправить его в /requesturl С application/x-www-form-urlencoded; charset=utf-8 заголовок Content-Type, как обычно ожидается, с запросами POST на конечных точках.

TL; DR

в ходе мое исследование я обнаружил, что ответ на эту проблему приходит во многих разных вариантах; некоторые из них очень запутаны и зависят от пользовательских функций, некоторые зависят от jQuery, а некоторые являются неполными, предполагая, что вам нужно только установить заголовок.

если вы просто установите Content-Type заголовок, конечная точка увидит данные POST, но это не будет в стандартном формате, потому что, если вы не предоставите строку в качестве data, или вручную сериализовать объект данных, все это будет сериализовано как JSON по умолчанию и может быть неправильно интерпретирован в конечной точке.

например, если правильный сериализатор не был установлен в приведенном выше примере, он будет рассматриваться в конечной точке как:

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

и это может привести к неожиданному разбору, например ASP.NET рассматривает его как null параметр name, с {"param1":"value1","param2":"value2"} как значение; или скрипач интерпретирует его по-другому, с {"param1":"value1","param2":"value2"} в качестве имени параметра и null как значение.


аналогично предложенному рабочему формату OP и ответу Денисона, за исключением использования просто $http и по-прежнему зависит от jQuery.

хорошая вещь об использовании jQuery здесь заключается в том, что сложные объекты передаются правильно; против ручного преобразования в Параметры URL, которые могут искажать данные.

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

когда у меня была эта проблема, параметр, который я отправлял, оказался массивом объектов вместо простого объекта.


только что обновил с углового 1.2 до 1.3, нашли проблему в коде. Преобразование ресурса приведет к бесконечному циклу, потому что (я думаю) $promise снова удерживает тот же объект. Может, это кому-то поможет...

Я мог бы исправить это:

[...]
  /**
 * 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;

angular.forEach(obj, function(value, name) {
+    if(name.indexOf("$promise") != -1) {
+        return;
+    }

    value = obj[name];
    if (value instanceof Array) {
        for (i = 0; i < value.length; ++i) {
[...]

я использую код принятого ответа (код Фелипе) некоторое время, и он отлично работает (спасибо, Фелипе!).

однако, недавно я обнаружил, что у него есть проблемы с пустыми объектами или массивами. Например, при отправке этого объекта:

{
    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("&");
    } ];
} ]);

это менее эффективно, чем код Фелипе, но я не думаю, что это имеет значение, так как он должен быть немедленным по сравнению с общими накладными расходами самого HTTP-запроса.

теперь PHP показывает:

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

насколько я знаю, невозможно получить PHP для признайте, что B. a и C-пустые массивы, но, по крайней мере, появляются ключи, что важно, когда есть код, который полагается на определенную структуру, даже когда она по существу пуста внутри.

Также обратите внимание, что он преобразует undefineds и nulls для пустых строк.


я решил это ниже кодов:

Сторона Клиента (Js):

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

обратите внимание, что данные-это объект.

на сервере (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);
        }
    }

надеюсь, это было полезно.


это не вина angular. Angular предназначен для работы в мире JSON. Поэтому, когда служба $http отправляет AJAX-запрос, она отправляет все ваши данные как полезную нагрузку, а не как данные формы, чтобы ваше бэкэнд-приложение могло обрабатывать их. Но jQuery делает некоторые вещи внутренне. Вы инструктируете модуль $ajax jQuery связывать данные формы как JSON, но перед отправкой AJAX-запроса он сериализовал JSON и add application/x-www-form-urlencoded заголовок. Таким образом, ваше бэкэнд-приложение может получать данные формы в виде параметров post, а не формат JSON.

но вы можете изменить поведение службы angular $http по умолчанию на

  1. добавить заголовок
  2. сериализация json

$httpParamSerializerJQLike-это встроенный сервис angular, который сериализует json таким же образом $.парам делает jQuery.

$http({
    method: 'POST',
    url: 'request-url',
    data: $httpParamSerializerJQLike(json-form-data),
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
    }
});

Если вам нужен плагин для сериализации данных формы в JSON, сначала используйте этот https://github.com/marioizquierdo/jquery.serializeJSON