【问题标题】:How do I POST urlencoded form data with $http without jQuery?如何在没有 jQuery 的情况下使用 $http 发布 urlencoded 表单数据?
【发布时间】:2016-11-21 21:36:16
【问题描述】:

我是 AngularJS 的新手,一开始我想开发一个只使用 AngularJS 的新应用程序。

我正在尝试使用 Angular 应用程序中的 $http 对服务器端进行 AJAX 调用。

为了发送参数,我尝试了以下方法:

$http({
    method: "post",
    url: URL,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: $.param({username: $scope.userName, password: $scope.password})
}).success(function(result){
    console.log(result);
});

这是可行的,但它也在 $.param 使用 jQuery。为了消除对 jQuery 的依赖,我尝试了:

data: {username: $scope.userName, password: $scope.password}

但这似乎失败了。然后我尝试了params

params: {username: $scope.userName, password: $scope.password}

但这似乎也失败了。然后我尝试了JSON.stringify

data: JSON.stringify({username: $scope.userName, password: $scope.password})

我为我的任务找到了这些可能的答案,但没有成功。难道我做错了什么?我敢肯定,AngularJS 会提供这个功能,但是如何提供呢?

【问题讨论】:

  • 我不知道什么是实际问题,但你试过这个$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
  • 你的第一个方法应该可以工作,$scope.userName 定义了吗?你为什么不试试data: data
  • @KevinB: 抱歉.. 我做了正确的编辑。
  • @mritunjay:对不起..我已经编辑了..我也在尝试。
  • @Veer 是否有效,还是您仍有问题?

标签: javascript jquery angularjs ajax angularjs-http


【解决方案1】:

我认为您需要做的是将数据从对象转换为 JSON 字符串,而不是转换为 url 参数。

From Ben Nadel's blog.

默认情况下,$http 服务会将传出的请求转换为 将数据序列化为 JSON,然后将其与内容一起发布- 类型,“应用程序/json”。当我们想将值作为 FORM 发布时 post,我们需要改变序列化算法和post数据 内容类型为“application/x-www-form-urlencoded”。

例如from here

$http({
    method: 'POST',
    url: url,
    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: {username: $scope.userName, password: $scope.password}
}).then(function () {});

更新

要使用 AngularJS V1.4 添加的新服务,请参阅

【讨论】:

  • 感谢您不使用 JQuery!
  • 如果我需要提交 multipart/form-data 怎么办?
  • 只要在angular.element下angular嵌入jqLit​​e,就可以简单return angular.element.param(obj);
  • @Vicary 请记住 param() 没有在 jqLit​​e 中实现 - code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
  • 这是另一种方式var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
【解决方案2】:

仅使用 AngularJS 服务的 URL 编码变量

使用 AngularJS 1.4 及更高版本,两个服务可以处理 POST 请求的 url 编码数据的过程,无需使用 transformRequest 或使用 jQuery 等外部依赖项来操作数据:

  1. $httpParamSerializerJQLike - 受 jQuery 的 .param() 启发的序列化程序(推荐

  2. $httpParamSerializer - Angular 自身用于 GET 请求的序列化程序

$http() 示例

$http({
  url: 'some/api/endpoint',
  method: 'POST',
  data: $httpParamSerializerJQLike($scope.appForm.data), // Make sure to inject the service you choose to the controller
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded' // Note the appropriate header
  }
}).then(function(response) { /* do something here */ });

See a more verbose Plunker demo


$http.post() 示例

$http.post(
    'some/api/endpoint',
    data: $httpParamSerializerJQLike($scope.appForm.data), // Make sure to inject the service you choose to the controller
    {
       headers: {
         'Content-Type': 'application/x-www-form-urlencoded' // Note the appropriate header
      }
    }
).then(function

$httpParamSerializerJQLike$httpParamSerializer 有何不同

一般来说,$httpParamSerializer 在处理复杂数据结构时使用的“传统” url 编码格式比$httpParamSerializerJQLike 少。

例如(忽略括号的百分比编码):

编码数组

{sites:['google', 'Facebook']} // Object with array property

sites[]=google&sites[]=facebook // Result with $httpParamSerializerJQLike

sites=google&sites=facebook // Result with $httpParamSerializer

对对象进行编码

{address: {city: 'LA', country: 'USA'}} // Object with object property

address[city]=LA&address[country]=USA // Result with $httpParamSerializerJQLike

address={"city": "LA", country: "USA"} // Result with $httpParamSerializer

【讨论】:

  • 我们如何在工厂内的 $resource 上使用它?
  • 应该是$http.({... 而不是`$http.post({...
  • @CarlosGranados 感谢您的关注。在此处和 Plunker 演示中更正了此错字。
  • 这在从 jQuery 迁移到 AngularJS 后完美运行
  • 这是我一直在寻找的 AngularJS 特定的答案。我希望发帖者能选择这个作为最佳答案。
【解决方案3】:

所有这些看起来都像是矫枉过正(或不起作用)......只需这样做:

$http.post(loginUrl, `username=${ encodeURIComponent(username) }` +
                     `&password=${ encodeURIComponent(password) }` +
                     '&grant_type=password'
).success(function (data) {

【讨论】:

  • 终于有点常识了
  • 这不会发送带有错误内容类型标头的请求吗?
  • 它对我有用...不确定标头是什么,但请求有效并且允许成功进行身份验证。你为什么不测试一下并告诉我们。
  • @Phil 我想这可能取决于服务器,我收到了错误的请求,直到我添加了 { headers: {'Content-Type': 'application/x-www-form-urlencoded'} }作为配置参数,或提供使用 $http(config) 构造函数,如 moices 的答案所示。无论哪种方式,这都优于公认的答案,因为它不会引入一些神奇的转换,也不需要用户使用一些辅助服务。谢谢!
【解决方案4】:

问题是JSON字符串格式,你可以在数据中使用一个简单的URL字符串:

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: 'username='+$scope.userName+'&password='+$scope.password
}).success(function () {});

【讨论】:

  • 您必须使用encodeURIComponent($scope.userName) 对数据进行url 编码,否则如果用户输入"&myCustomParam=1" 之类的值,您的参数将会损坏
  • 这是唯一对我有用的答案!我跳过了成功,但是$http格式很好
【解决方案5】:

这是它应该的方式(请不要更改后端......当然不是......如果你的前端堆栈不支持application/x-www-form-urlencoded,那么就把它扔掉......希望AngularJS支持!

$http({
     method: 'POST',
     url: 'api_endpoint',
     headers: {'Content-Type': 'application/x-www-form-urlencoded'},
     data: 'username='+$scope.username+'&password='+$scope.password
 }).then(function(response) {
    // on success
 }, function(response) {
    // on error
 });

使用 AngularJS 1.5 就像一个魅力

各位,给点建议吧:

  • 在处理 $http 时使用 promises .then(success, error),忘记 .sucess.error 回调(因为它们已被弃用)

  • 来自 angularjs 网站here您不能再使用 JSON_CALLBACK 字符串作为占位符来指定回调参数值的位置。

如果您的数据模型比用户名和密码更复杂,您仍然可以这样做(如上所述)

$http({
     method: 'POST',
     url: 'api_endpoint',
     headers: {'Content-Type': 'application/x-www-form-urlencoded'},
     data: json_formatted_data,
     transformRequest: function(data, headers) {
          return transform_json_to_urlcoded(data); // iterate over fields and chain key=value separated with &, using encodeURIComponent javascript function
     }
}).then(function(response) {
  // on succes
}, function(response) {
  // on error
});

encodeURIComponent 的文档可以在 here 找到

【讨论】:

    【解决方案6】:

    如果是表单,请尝试将标题更改为:

    headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";
    

    如果它不是一个表单和一个简单的 json,那么试试这个头:

    headers[ "Content-type" ] = "application/json";
    

    【讨论】:

    • 没有收到任何东西。我仍然收到空白 $_POST 数组。!
    • 你的控制器中有这个 $http 调用吗?
    • 还有一件事是你的服务器端php?
    • 我找到了同样的解决方案你还在@Veer遇到问题吗?
    【解决方案7】:

    来自$http 文档,这应该可以工作..

      $http.post(url, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
        .success(function(response) {
             // your code...
         });
    

    【讨论】:

    • @Kevin 我对此不确定,但是..有一次当我尝试发送字符串时,它向我显示了一个错误
    • @KevinB 很好..我明白了..我认为在发送字符串时需要更改标题..stackoverflow.com/a/20276775/2466168
    • 请注意,发送正确的headers 不会影响data,它仍然需要以一种或另一种方式进行urlencoded。
    • 数据仍以 json 格式发送,您必须将数据编码为 x-www-form-urlencoded 仅添加标头是不够的
    【解决方案8】:
    $http({
    
        method: "POST",
        url: "/server.php",
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        data: "name='Олег'&age='28'",
    
    
    }).success(function(data, status) {
        console.log(data);
        console.log(status);
    });
    

    【讨论】:

    【解决方案9】:

    您只需要发布普通的 javascript 对象即可

               var request = $http({
                    method: "post",
                    url: "process.cfm",
                    transformRequest: transformRequestAsFormPost,
                    data: { id: 4, name: "Kim" }
                });
    
                request.success(
                    function( data ) {
                        $scope.localData = data;
                    }
                );
    

    如果你有 php 作为后端,那么你需要做更多的修改.. checkout this link 来修复 php 服务器端

    【讨论】:

    • 这完全不是他所要求的,他特别问他如何才能将它们作为 x-www-form-urlencoded 获得,因为他在发布 json 内容时遇到了问题。
    • @ppetermann 你在否决之前检查了问题的编辑历史......
    【解决方案10】:

    虽然答案较晚,但我发现 angular UrlSearchParams 对我来说效果很好,它还负责参数的编码。

    let params = new URLSearchParams();
    params.set("abc", "def");
    
    let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded'});
    let options = new RequestOptions({ headers: headers, withCredentials: true });
    this.http
    .post(UrlUtil.getOptionSubmitUrl(parentSubcatId), params, options)
    .catch();
    

    【讨论】:

      【解决方案11】:

      这对我有用。我将 angular 用于前端,将 laravel php 用于后端。在我的项目中,angular web 将 json 数据发送到 laravel 后端。

      这是我的角度控制器。

      var angularJsApp= angular.module('angularJsApp',[]);
      angularJsApp.controller('MainCtrl', function ($scope ,$http) {
      
          $scope.userName ="Victoria";
          $scope.password ="password"
      
      
             $http({
                  method :'POST',
                  url:'http://api.mywebsite.com.localhost/httpTest?callback=JSON_CALLBACK',
                  data: { username :  $scope.userName , password: $scope.password},
                  headers: {'Content-Type': 'application/json'}
              }).success(function (data, status, headers, config) {
                  console.log('status',status);
                  console.log('data',status);
                  console.log('headers',status);
              });
      
      });
      

      这是我的 php 后端 laravel 控制器。

      public function httpTest(){
              if (Input::has('username')) {
                  $user =Input::all();
                  return  Response::json($user)->setCallback(Input::get('callback'));
              }
          }
      

      这是我的 laravel 路由

      Route::post('httpTest','HttpTestController@httpTest');
      

      浏览器中的结果是

      状态 200
      数据 JSON_CALLBACK({"username":"Victoria","password":"password","callback":"JSON_CALLBACK"}); httpTesting.js:18 头函数 (c){a||(a=sc(b));return c?a[K(c)]||null:a}

      有一个叫做 postman 的 chrome 扩展。您可以使用它来测试您的后端 url 是否有效。 https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en

      希望我的回答对你有所帮助。

      【讨论】:

        猜你喜欢
        • 2017-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-07
        • 1970-01-01
        相关资源
        最近更新 更多