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

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>up test</title>
</head>
<body>
<h1>上传测试</h1>
<p></p>
<br>
<form enctype="multipart/form-data" id="doUpfile">
<input type="file" name="file">
</form>
<button id="yes">Do it!</button>
<script src="./libs/jquery.js"></script>
<script src="./libs/jquery.form.js"></script> <script>
window.localStorage.removeItem("token");
var userinfo="username=test&password=123";
$.ajax({
"url":"http://192.168.1.1:9090/common/users/logon",
"type":"POST",
"crossDomain":true,
"data":userinfo,
"success":parse1
})
function parse1(data1){
window.localStorage.setItem("token",data1);
alert("新的token:"+window.localStorage.getItem("token"));
}
alert("token值是:"+window.localStorage.getItem("token"));
alert(userinfo);
var options={
"url":"http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken="+window.localStorage.getItem("token"),
"type":"POST",
"success":parse2,
"error":parse3
} $("#yes").on("click",upSubmit);
function upSubmit(){
$(function(){
$("#doUpfile").ajaxSubmit(options);
})
}
function parse2(data2){
console.log(data2);
alert("上传成功,图片返回值为:"+data2);
alert(JSON.stringify(options));
}
function parse3(data3){
alert("上传出错,原因为:"+data3);
alert(JSON.stringify(data3));
alert(JSON.stringify(options));
alert("token值是:"+window.localStorage.getItem("token"));
}
</script>
</body>
</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内核,但肯定会有所区别)。

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

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>up test</title>
</head>
<body>
<h1>最新上传测试 version 12-11-options单独定义</h1>
<p></p>
<br>
<form enctype="multipart/form-data" id="doUpfile">
<input type="file" name="file">
</form>
<button id="yes">Do it!</button>
<script src="./libs/jquery.js"></script>
<script src="./libs/jquery.form.js"></script> <script>
window.localStorage.removeItem("token");
var userinfo="username=pengli&password=pengli";
$.ajax({
"url":"http://192.168.1.1:9090/common/users/logon",
"type":"POST",
"crossDomain":true,
"data":userinfo,
"success":parse1
})
function parse1(data1){
window.localStorage.setItem("token",data1);
alert("新的token:"+window.localStorage.getItem("token"));
}
alert("第32行,现在的token值是:"+window.localStorage.getItem("token"));
alert(userinfo); var options={
"url":"http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken="+window.localStorage.getItem("token"),
"type":"POST",
"success":parse2,
"error":parse3
}
alert("第41行,options里面的操作:"+options["url"]);
$("#yes").on("click",upSubmit);
function upSubmit(){
$(function(){
$("#doUpfile").ajaxSubmit(options);
})
}
function parse2(data2){
console.log(data2);
alert("上传成功,图片返回值为:"+data2);
alert("最后的token值是:"+window.localStorage.getItem("token"));
alert(JSON.stringify(options));
}
function parse3(data3){
alert("上传出错,原因为:"+data3);
alert(JSON.stringify(data3));
alert(JSON.stringify(options));
alert("最后的token值是:"+window.localStorage.getItem("token"));
}
</script>
</body>
</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()的操作单独定义出来,而是要直接传进去,即:

 function upSubmit(){
$(function(){
$("#doUpfile").ajaxSubmit({
"url":"http://192.168.1.1:9090/club_activity/club/image/clubImage?authToken="+window.localStorage.getItem("token"),
"type":"POST",
"success":parse2,
"error":parse3
});
})
}

还有需要注意的一个地方是,使用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

cordova+jquery form上传里面的一些诡异坑的更多相关文章

  1. jquery.form上传文件

    建立test文件夹 PHP代码: <?php //var_dump($_FILES['file']);exit; if(isset($_GET['option']) && $_G ...

  2. jQuery.form 上传文件

    今年大部分是都在完善产品,这几天遇到了一个问题,原来的flash组件不支持苹果浏览器,需要改.在网上搜了下,看到一个jQuery.form插件可以上传文件,并且兼容性很好,主要浏览器大部分都兼容,插件 ...

  3. IE8/9 JQuery.Ajax 上传文件无效

    IE8/9 JQuery.Ajax 上传文件有两个限制: 使用 JQuery.Ajax 无法上传文件(因为无法使用 FormData,FormData 是 HTML5 的一个特性,IE8/9 不支持) ...

  4. 强大的支持多文件上传的jQuery文件上传插件Uploadify

    支持多文件上传的jQuery文件上传插件Uploadify,目前此插件有两种版本即Flash版本和HTML5版本,对于HTML5版本会比较好的支持手机浏览器,避免苹果手机Safari浏览器不支持Fla ...

  5. jQuery文件上传插件Uploadify(转)

    一款基于flash的文件上传,有进度条和支持大文件上传,且可以多文件上传队列. 这款在flash的基础上增加了html5的支持,所以在移动端也可以使用. 由于官方提供的版本是flash免费,html5 ...

  6. jQuery文件上传插件jQuery Upload File 有上传进度条

    jQuery文件上传插件jQuery Upload File 有上传进度条 jQuery文件上传插件jQuery Upload File,插件使用简单,支持单文件和多文件上传,支持文件拖拽上传,有进度 ...

  7. 聊一聊jquery文件上传(支持多文件上传)

    谈到文件上传,现在一般都用现成的组件可以使用.PC端的可以使用uploadify.针对微网站H5也有uploadifive.但是这组件并不能满足各种场景的需求,例如:预览 切图 放大缩小,取消之类的. ...

  8. ASP.NET Jquery+ajax上传文件(带进度条)

    效果图 支持ie6+,chrome,ie6中文文件名会显示乱码. 上传时候会显示进度条. 需要jquery.uploadify.js插件,稍后会给出下载 前台代码 <%@ Page Langua ...

  9. MVC文件上传 - 使用jquery异步上传并客户端验证类型和大小

    本篇体验MVC上传文件,从表单上传过渡到jquery异步上传. MVC最基本的上传文件是通过form表单提交方式 □ 前台视图部分 <% using(Html.BeginForm("F ...

随机推荐

  1. 在python实现加密的方式总结

    基础知识扫盲 对称加密 对称密钥加密 , 又叫私钥加密.即信息发送的方和接受方用一个密钥去加密和揭秘数据. 最大的优势是 加解密速度快,适合对大量数据进行加密, 对称加密的缺点是密钥的管理和分配, 换 ...

  2. PHP 限制访问ip白名单

    一  上代码 config.php //ip白名单配置 'ipWlist'=>[ 'ifFilter'=>true, //是否开启白名单功能 'wlist'=>[ '10.0.0.1 ...

  3. StartDT AI Lab | 智能运筹助力企业提升决策效率、优化决策质量

    在人工智能和大数据时代,越来越多的云上数据和越来越智能的模型开始辅助人们做出各种最优决策,从运营效率.成本节约.最优配置等方方面面,实现降本增效,进一步提升商业效率.京东.美团.滴滴.顺丰等众多知名厂 ...

  4. hibernate 持久化对象 save

    hibernate 持久化对象 save new出来的user对象是游离状态的对象,执行session.save()方法保存后,user对象就变为持久化了,持久化的对象跟数据库表双向绑定的意思, 对象 ...

  5. 线性反馈移位寄存器(LFSR)-非线性反馈移位寄存器的verilog实现(产生伪随机数)

    一.线性反馈移位寄存器(LFSR) 通过对事先选定的种子做运算使得人工生成的伪随机序列的过程,在实际中,随机种子的选择决定了输出的伪随机序列的不同,也就是说随机种子的选择至关重要. 产生伪随机数的方法 ...

  6. 对xgboost中dump_model生成的booster进行解析

    xgboost原生包中有一个dump_model方法,这个方法能帮助我们看到基分类器的决策树如何选择特征进行分裂节点的,使用的基分类器有两个特点: 二叉树: 特征可以重复选择,来切分当前节点所含的数据 ...

  7. bootstrap 学习 ---css样式学习

    bootstrap 适用于响应式布局,移动设备优先的web项目 1.学习bootstrap需要引入bootstrap的css,jquery,bootstrap的js,注意:jquery文件必须在boo ...

  8. 1.redis安装配置

    Redis 1.Redis安装: 说明: 1.也是一种类似于Memcached的kev-value机制的存储服务 2.是非关系型数据库(NoSQL)的一种. 3.官网:www.redis.io,中文网 ...

  9. 结构体struct,类class

    1.struct,值类型,结构体会自动生成初始化方法,class是引用类型 struct Person { var name : String var age : Int func simpleDes ...

  10. jmeter测试get post 笔记

    0 环境 系统环境:win7 1 操作 1 post 新建线程组 2 get 和post新建类似 http请求 只是新建一个参数化我测试的2个url http://127.0.0.1:8080/cry ...