如何在没有jQuery的情况下使用$ http发布urlencode表单数据?


195

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

我正在尝试使用$httpAngular应用程序向服务器端进行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);
});

这是可行的,但同时也在使用jQuery $.param。为了消除对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}});
Mritunjay 2014年

1
您的第一个方法应该起作用,是否已$scope.userName定义?你为什么不尝试data: data
凯文

@KevinB:对不起..我进行了正确的编辑。
Veer Shrivastav 2014年

@mritunjay:对不起。我进行了编辑。
Veer Shrivastav 2014年

@Veer起作用了还是还是有问题?
V31 2014年

Answers:


409

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

来自Ben Nadel的博客

默认情况下,$ http服务将通过将数据序列化为JSON然后使用内容类型“ application / json”将其发布来转换外发请求。当我们想将值作为FORM发布时,我们需要更改序列化算法,并以内容类型“ application / x-www-form-urlencoded”发布数据。

这里的例子。

$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中添加的新服务,请参阅


41
感谢您不使用JQuery!
OverMars

1
如果我需要提交多部分/表单数据怎么办?
Dejell

2
只要角嵌入影片jqLit​​e下angular.element,你可以简单return angular.element.param(obj);
维卡里

4
@Vicary请记住,jqLit​​e中未实现param()- code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
Alex Pavlov

1
这是另一种方式 var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
test30

136

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

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

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

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

用法示例

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

查看更详细的Plunker演示


如何$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上使用它?
stilllife 2015年

2
$http.({...改为of`$http.post({...
卡洛斯·格拉纳多斯

@CarlosGranados感谢您的关注。在此处和在Plunker演示中更正了此错字。
波阿斯2015年

从jQuery迁移到AngularJS后,此方法非常有效
zero298 '16

4
这是我正在寻找的特定于AngularJS的答案。我希望张贴者选择这个作为最佳答案。
张建忠(Marty Chang)

61

所有这些看起来都像是过度杀伤(或不起作用)...只需执行以下操作:

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

11
最后是一些常识
jlewkovich

这不会使用错误的内容类型标头发送请求吗?
菲尔

它对我有用...不确定标题是什么,但是请求有效,并且允许成功进行身份验证。您为什么不进行测试并告诉我们。
Serj Sagan

5
@Phil我猜想这可能取决于服务器,我的请求很糟糕,直到我添加了{标头:{'Content-Type':'application / x-www-form-urlencoded'}}作为配置arg或供应使用$ http(config)构造函数,如moices的答案所示。无论哪种方式,这都优于公认的答案,因为它不会带来任何神奇的转变,也不需要用户提供一些辅助服务。谢谢!
Bungle先生

23

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

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

7
您必须使用encodeURIComponent($scope.userName)url编码数据,否则如果用户输入值,则参数将被破坏"&myCustomParam=1"
IvanHušnjak2015年

2
这是唯一对我有用的答案!我略过成功,但$ http格式很好
xenteros

4

这是应该的方式(请不要更改后端……肯定不……如果您的前端堆栈不支持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中像魅力一样工作

人民,让我们给您一些建议:

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

  • 在angularjs网站上您不能再将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可以在这里找到


3

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

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

如果它不是表单和简单的json,请尝试以下标头:

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

没有收到任何东西。我仍然收到空白$_POST数组。
Veer Shrivastav 2014年

这是您的控制器中的$ http呼叫吗?
V31

还有一件事是您的服务器端php?
V31

我已经找到了相同的解决方案,您是否仍然遇到问题@Veer?
V31 2014年

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

4
仅代码答案对社区没有用。请查看“ 如何回答
abpatil

1

$ http docs开始,这应该有效。

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

@Kevin我对此不太确定,但是..当我尝试发送一个字符串时,它向我显示了一个错误
Srinath 2014年

@KevinB Fine..I了it..i认为需要头在发送一个字符串改变.. stackoverflow.com/a/20276775/2466168
Srinath

1
请注意,发送正确的消息headers不会影响data仍然需要以一种或另一种方式进行urlencode的。
波阿斯2015年

数据仍以json格式发送,您必须将数据编码为x-www-form-urlencoded,仅添加标头是不够的
wendellmva

1

您需要发布普通的javascript对象,别无其他

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

            request.success(
                function( data ) {
                    $scope.localData = data;
                }
            );

如果您有php作为后端,那么您将需要做一些其他修改。.检出此链接以修复php服务器端


那完全不是他想要的,他特别地问他如何将它们以x-www-form-urlencoded格式获取,因为他遇到了发布json内容的问题。
ppetermann

@ppetermann你检查问题的编辑历史downvoting ..之前
harishr

1

尽管答案很晚,但我发现有角度的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();

0

这对我有用。我将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));返回c?a [K(c)] || null:a}

chrome扩展名为postman。您可以用来测试后端网址是否正常。 https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=zh-CN

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.