cordova+jquery form上传里面的一些诡异坑

在浏览器里面执行很正常的代码,打包到手机上测试就出问题了,浏览器中的执行版本如下:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>up test</title>
 6 </head>
 7 <body>
 8     <h1>上传测试</h1>
 9     <p></p>
10     <br>
11     <form enctype="multipart/form-data" id="doUpfile">
12         <input type="file" name="file">
13     </form>
14     <button id="yes">Do it!</button>
15     <script src="./libs/jquery.js"></script>
16     <script src="./libs/jquery.form.js"></script>
17     
18     <script>
19     window.localStorage.removeItem("token");
20     var userinfo="username=test&password=123";
21     $.ajax({
22         "url":"http://192.168.1.1:9090/common/users/logon",
23         "type":"POST",
24         "crossDomain":true,
25         "data":userinfo,
26         "success":parse1
27     })
28     function parse1(data1){
29         window.localStorage.setItem("token",data1);
30         alert("新的token:"+window.localStorage.getItem("token"));        
31     }
32     alert("token值是:"+window.localStorage.getItem("token"));
33     alert(userinfo);
34     var options={
35             "url":"http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken="+window.localStorage.getItem("token"),
36             "type":"POST",
37             "success":parse2,
38             "error":parse3
39         }
40         
41     $("#yes").on("click",upSubmit);
42     function upSubmit(){
43         $(function(){
44             $("#doUpfile").ajaxSubmit(options);
45         })
46     }
47     function parse2(data2){
48         console.log(data2);
59         alert("上传成功,图片返回值为:"+data2);
60         alert(JSON.stringify(options));
61     }
62     function parse3(data3){
63         alert("上传出错,原因为:"+data3);
66         alert(JSON.stringify(data3));
67         alert(JSON.stringify(options));
68         alert("token值是:"+window.localStorage.getItem("token"));
69     }
70     </script>
71 </body>
72 </html>

最初的问题是进入app后点击上传选择文件时,如果直接选择文件的话app就崩溃了,但是如果从侧边栏选择进入“图库”,再在图库里面选择相册,进入相册之后再点选图片,就可以正常选择图片了(这是第一个诡异的地方),直到现在都不知道是为什么。

第二个问题是每次进入app之后弹出来的token是Null(这说明第19行的代码此时已经被执行过了),再弹出userinfo的值,过后再弹出“新的token是:xxxxxx”,也就是说第32行的代码先于第21行的ajax请求执行了(这里代码执行顺序为19-32-33-21),当然也可能不是先于ajax执行,而是先于ajax里面的回调函数parse1执行了。

然后针对第二个问题,一开始以为是localStorage的写法问题,因为刚开始我用的是window.localStorage.key=value的方式来对localStorage存取的,但是后来在stackoverflow上查到在手机上据说是要这么写window.localStorage.setItem(key,value),window.localStorage.getItem(key),window.localStorage.removeItem(key),或者window.localStorage.[key]=value的方式,于是乎改成用setItem()来设置值,但是上传还是失败了,还是因为token的问题导致身份验证失败。仔细一看,每次提交请求的时候,带上的token都是上次的token,但是每次进入app的时候都会发一次请求获得新的token,猜想可能是js代码在浏览器上和在手机上的解析方式不太一样(虽然都是webkit内核,但肯定会有所区别)。

为了验证猜想,加了几条打印代码,作为调试用:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>up test</title>
 6 </head>
 7 <body>
 8     <h1>最新上传测试 version 12-11-options单独定义</h1>
 9     <p></p>
10     <br>
11     <form enctype="multipart/form-data" id="doUpfile">
12         <input type="file" name="file">
13     </form>
14     <button id="yes">Do it!</button>
15     <script src="./libs/jquery.js"></script>
16     <script src="./libs/jquery.form.js"></script>
17     
18     <script>
19     window.localStorage.removeItem("token");
20     var userinfo="username=pengli&password=pengli";
21     $.ajax({
22         "url":"http://192.168.1.1:9090/common/users/logon",
23         "type":"POST",
24         "crossDomain":true,
25         "data":userinfo,
26         "success":parse1
27     })
28     function parse1(data1){
29         window.localStorage.setItem("token",data1);
30         alert("新的token:"+window.localStorage.getItem("token"));        
31     }
32     alert("第32行,现在的token值是:"+window.localStorage.getItem("token"));
33     alert(userinfo);
34     
35     var options={
36             "url":"http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken="+window.localStorage.getItem("token"),
37             "type":"POST",
38             "success":parse2,
39             "error":parse3
40         }
41     alert("第41行,options里面的操作:"+options["url"]);    
42     $("#yes").on("click",upSubmit);
43     function upSubmit(){
44         $(function(){
45             $("#doUpfile").ajaxSubmit(options);
46         })
47     }
48     function parse2(data2){
49         console.log(data2);
50         alert("上传成功,图片返回值为:"+data2);
51         alert("最后的token值是:"+window.localStorage.getItem("token"));
52         alert(JSON.stringify(options));
53     }
54     function parse3(data3){
55         alert("上传出错,原因为:"+data3);
56         alert(JSON.stringify(data3));
57         alert(JSON.stringify(options));
58         alert("最后的token值是:"+window.localStorage.getItem("token"));
59     }
60     </script>
61 </body>
62 </html>

在手机里面,代码的执行顺序为:先弹出第32行(现在的token值是Null,当然,这说明19行是最先执行的),紧接着弹出第33行的userinfo值,第三次是执行第41行的代码(第41行,options里面的操作:http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken=null),最后弹出第30行的代码(新的token值是xxxxx)。

而在浏览器中,执行的效果为:第32行(现在的token为Null),紧接着是第30行(新的token值是xxxx,说明此时已经取到了token),再然后是执行第33行代码,弹出Userinfo的值,最后是第41行代码,Options操作里面的token已经不是Null,而是获取到的token了。也就是说,Js在浏览器和在手机上的执行确实存在顺序上的不一致,这种解析方式的差异,多半就是webkit内核不同导致的。

解决方式有两种:第一种是单独另写一个登陆页,现在这个页面发起请求获得token,然后再进入文件上传页面上传文件。另一种,如果非得把上传和提交写在一个页面里面,那就不能把$.ajaxSubmit()的操作单独定义出来,而是要直接传进去,即:

 1 function upSubmit(){
 2         $(function(){
 3             $("#doUpfile").ajaxSubmit({
 4             "url":"http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken="+window.localStorage.getItem("token"),
 5             "type":"POST",
 6             "success":parse2,
 7             "error":parse3
 8             });
 9         })
10     }

还有需要注意的一个地方是,使用cordova打包app时,需要加入whitelist插件,否则上传会一直返回404错误,具体的请参考:http://gxxsite.com/content/view/id/197.html

另外由于在手机上传文件,需要文件访问权限,cordova打包时还需要加入cordova-plugin-file和cordova-plugin-file-transfer两个插件。

 有关cordova打包的具体细节,参考这里:http://blog.csdn.net/g252691665/article/details/50259471

原文地址:https://www.cnblogs.com/debugzer0/p/5037999.html