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

 <!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. HDU -1166 线段树

    #include <algorithm> #include <iostream> #include<sstream> #include<cstring> ...

  2. opencv+tkinter制作HsvMaster(一)

    这两天看opencv-python的HSV色彩空间,在写程序时发现用HSV来提取图像区域是件令人恶心的麻烦事.拿阈值分割做个对比,阈值最多也就一两个参数需要调整:但是HSV需要对三个通道调整上下限,也 ...

  3. dubbo的超时处理和配置覆盖

    提供者的设置方式 消费者的设置方式 配置原则 dubbo推荐在Provider上尽量多配置Consumer端属性: 1.作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数 ...

  4. [HNOI2019]鱼(计算几何)

    看到数据范围n<=1000,但感觉用O(n^2)不现实,所以考虑方向应该是O(n^2logn). 一种暴力做法:用vector存到1点相同的2点和到2点相同的1点,然后枚举A,枚举BC,再枚举D ...

  5. Flume(二) —— 自定义拦截器、Source、Sink

    自定义拦截器 自定义Source 自定义Sink 引入依赖 <dependency> <groupId>org.apache.flume</groupId> < ...

  6. linux4.11内核设备编译时出现的问题(参考博客并更改的)

    AllWinnerH3 linux4.11版本的bsp下载: https://pan.baidu.com/s/1mhU4a8K 密码: b375 H3-linux4.11_bsp目录就是所需的源码及编 ...

  7. js获取当前页面名称

    // 取当前页面名称(不带后缀名) function pageName() { var a = location.href; var b = a.split("/"); var c ...

  8. iOS 一种很方便的构造TarBar

    直接在TarBarController中操作,代码如下: #import "DLTabBarController.h" #import "ViewController.h ...

  9. Automatic Setup of a Humanoid

    The humanoid animation option in Unity 4 makes it possible to retarget the same animations to differ ...

  10. 00 - 准备 Anaconda 环境

    Anaconda 环境 官方下载安装包:https://www.anaconda.com/download/ Anaconda Navigtor :用于管理工具包和环境的图形用户界面,后续涉及的众多管 ...