• 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

  • 相关阅读:
    Excel求值表达式——太好用了
    CPU保护模式深入探秘
    用QT创建WINDOWS服务程序
    windows服务怎么向应用程序发消息(部署在同一台机,非SCOKET)
    TCP的流量控制和拥塞控制
    PHP:执行模型和内存模型
    Web API CSRF保护实现
    C#中易混淆的知识点
    字符串合并与拆分写法小结
    zabbix实现对磁盘动态监控
  • 原文地址:https://www.cnblogs.com/debugzer0/p/5037999.html
Copyright © 2020-2023  润新知