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

 <!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. jenkins-master-slave节点配置总结

    一.jenkins分布式简单介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能 二.jenk ...

  2. vue-resource CRUD示例

    GET请求 var demo = new Vue({ el: '#app', data: { gridColumns: ['customerId', 'companyName', 'contactNa ...

  3. 阿里云ECS搭建邮件服务

    安装mailx [root@db ~]# yum install -y mailx [root@db ~]# vim /etc/mail.rc 设置发件人信息 ..... set from=yunwe ...

  4. 你必须知道的基本位运算技巧(状压DP、搜索优化都会用到)

    一. 位操作基础 基本的位操作符有与.或.异或.取反.左移.右移这6种,它们的运算规则如下所示: 符号 描述 运算规则 & 与 两个位都为1时,结果才为1 | 或 两个位都为0时,结果才为0 ...

  5. iTOP-4418开发板Qt Creator 编译注意事项

    用“Qt Creator3.2.2”打开“qt4.7.1”环境下的工程文件可能会提示版本太旧.环境不匹 配导致程序无法编译,解决办法:建立新的工程把测试程序代码粘贴上去即可(界面需要自己 添加). 在 ...

  6. [Algo] 306. Check If Linked List Is Palindrome

    Given a linked list, check whether it is a palindrome. Examples: Input:   1 -> 2 -> 3 -> 2 ...

  7. Linux介绍,基本命令

  8. Java任务调度框架之分布式调度框架XXL-Job介绍

    ​ Java任务调度框架之分布式调度框架XXL-Job介绍及快速入门 调度器使用场景: Java开发中经常会使用到定时任务:比如每月1号凌晨生成上个月的账单.比如每天凌晨1点对上一天的数据进行对账操作 ...

  9. Matlab高级教程_第二篇:MATLAB和C#一些常用的矩阵运算方法的转换

    1.相关方法已经生产引用,直接调用的结果如下: 2. 相关调用代码如下: using System; using System.Collections.Generic; using System.Li ...

  10. [LC] 796. Rotate String

    We are given two strings, A and B. A shift on A consists of taking string A and moving the leftmost ...