先给大家分析下微信浏览器上传图片bug的原因

微信在新版本中采用的是自己的X5内核浏览器,而在较老的版本中还有可能是安卓的原生浏览器。具体的环境我也不太了解,但是经过实际多台安卓机型的测试,我采取的方案可以基本确保在安卓机中微信浏览器的成功上传。苹果机型没问题,因为微信的ios客户端使用的是Safari的内核,没有各种坑,且效果最好。

这里给出一个 WebUploader 官方关于移动端适配的 issues 链接。里面提供的方法确实有效,但就是解决的方案并没有很清楚的展示出来,从该issues中有好几个人用户提出如何修改就能知道了。

开始时遇到的问题

环境

后台使用 Spring MVC [V 4.08],前端使用一个开源的 HTML5 框架

问题

ios可完美上传,安卓手机一半以上不太支持,出现进度条卡死,图片无法上传成功而且只能上传png格式图片的问题(后来证明是由于压缩失败引起的,在解决中详细指出)。发布到服务器上正式运营以后,发现部分用户只填写了文字信息,无法上传图片,不好统计数据,但是这样的 BUG 率显然是不行的,接下来就给出我的解决方案吧,经过实际测试应该是没问题的,不保证完全有效,因为原理不是太清楚,仅供参考。

后来的解决方案

第一步,sendAsBinary: true

我先是按照 issues 中给出的第一个解决方法,设置 sendAsBinary: true,后台不做任何修改的情况下会产生 500 的错误,但是此时解决了进度条卡死的问题(当然啊!图片直接就上传失败了!)……根据issues中 2betop 的回答,此时获取文件应该是直接获取文件的二进制流。

之前获取图片的方式是使用 Spring 自带的 MultipartHttpServletRequest 将 HttpServletRequest 的实例 request 转换,然后获取多个文件的信息。下方代码根据实际代码删减不必要的细枝末节得出。

MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

// 获取上传文件的列表

Map fileMap = multipartRequest.getFileMap();

// 图片上传前的原始名

String originalName;

// 循环获取多文件上传时文件列表中的每个文件对象

for (Map.Entry entity : fileMap.entrySet()) {

// 上传文件

MultipartFile mf = entity.getValue();

// 文件上传前的原始名

originalName = mf.getOriginalFilename();

// 文件扩展名

String fileExt = originalName.substring(originalName.lastIndexOf(".") + 1).toLowerCase();

// 文件的绝对路径File

File uploadFile = new File(uploadAbsolutePath + "/" + newName);

try {

FileCopyUtils.copy(mf.getBytes(), uploadFile);

} catch (IOException ioException) {

logger.error("图片保存到文件夹中出错!", ioException);

} catch (Exception e) {

logger.error("文件没有复制到指定的目录下", e);

}

}

这是原本的获取方式,500 报错时指示是第一行代码出错,无法转换,因为此时 WebUploader 在设置了 sendAsBinary: true后 并没有使用 content-type: multipart/form-data 上传文件,而是 content-type: application/ocet-stream,源码中也是这么写的,但是实际获取的请求头中并没有看到这个字段,而只是图片的类型.下列给出我使用 Chrome 的 devTools 保存下来的请求信息,只贴出 headers 中的字段值(针对同一个上传 API 提出请求):

500 错误时的请求头

"url": "http://localhost:8787/lostFound/front/release/upload?releaseType=0&orderId=330&id=WU_FILE_1&name=20140120_035024000_iOS.jpg&type=image%2Fjpeg&lastModifiedDate=Sat+Jan+31+2015+01%3A32%3A34+GMT%2B0800+(%C3%A4%C2%B8%C2%AD%C3%A5%C2%9B%C2%BD%C3%A6%C2%A0%C2%87%C3%A5%C2%87%C2%86%C3%A6%C2%97%C2%B6%C3%A9%C2%97%C2%B4)&size=81666",

"httpVersion": "HTTP/1.1",

"headers": [

{

"name": "Origin",

"value": "http://localhost:8787"

},

{

"name": "Accept-Encoding",

"value": "gzip, deflate"

},

{

"name": "Host",

"value": "localhost:8787"

},

{

"name": "Accept-Language",

"value": "zh-CN,zh;q=0.8"

},

{

"name": "User-Agent",

"value": "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"

},

{

"name": "Content-Type",

"value": "image/jpeg"

},

{

"name": "Accept",

"value": "*/*"

},

{

"name": "Referer",

"value": "http://localhost:8787/lostFound/"

},

{

"name": "Cookie",

"value": "JSESSIONID=2839511C91E9ECE62D155C6EE18F3259; JSESSIONID=64B53863E1C7D82B96927F298A864E18"

},

{

"name": "Connection",

"value": "keep-alive"

},

{

"name": "Content-Length",

"value": "81666"

}

],

"queryString": [

{

"name": "releaseType",

"value": "0"

},

{

"name": "orderId",

"value": "330"

},

{

"name": "id",

"value": "WU_FILE_1"

},

{

"name": "name",

"value": "20140120_035024000_iOS.jpg"

},

{

"name": "type",

"value": "image%2Fjpeg"

},

{

"name": "lastModifiedDate",

"value": "Sat+Jan+31+2015+01%3A32%3A34+GMT%2B0800+(%C3%A4%C2%B8%C2%AD%C3%A5%C2%9B%C2%BD%C3%A6%C2%A0%C2%87%C3%A5%C2%87%C2%86%C3%A6%C2%97%C2%B6%C3%A9%C2%97%C2%B4)"

},

{

"name": "size",

"value": "81666"

}

],

"bodySize": 0

在不修改 sendAsBinary: true 之前成功上传的请求头

"url": "http://localhost:8787/lostFound/front/release/upload",

"httpVersion": "HTTP/1.1",

"headers": [

{

"name": "Origin",

"value": "http://localhost:8787"

},

{

"name": "Accept-Encoding",

"value": "gzip, deflate"

},

{

"name": "Host",

"value": "localhost:8787"

},

{

"name": "Accept-Language",

"value": "zh-CN,zh;q=0.8"

},

{

"name": "User-Agent",

"value": "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"

},

{

"name": "Content-Type",

"value": "multipart/form-data; boundary=----WebKitFormBoundaryLeVpfViKLf1xLdIr"

},

{

"name": "Accept",

"value": "*/*"

},

{

"name": "Referer",

"value": "http://localhost:8787/lostFound/"

},

{

"name": "Cookie",

"value": "JSESSIONID=A76C40D04276501F54675AA02AE61467; JSESSIONID=64B53863E1C7D82B96927F298A864E18"

},

{

"name": "Connection",

"value": "keep-alive"

},

{

"name": "Content-Length",

"value": "44210"

}

],

"queryString": [],

"bodySize": 929,

比较两者的区别,发现区别:

content-type: 修改为 sendAsBinary: true 以后,这个值变为 image/jpeg, 而之前是 multipart/form-data,所以不能再使用 MultipartHttpServletRequest,后端获取改为获取文件流。

queryString:启用二进制上传以后,参数直接添加到 Url 中。

bodySize:启用之后变为 0,启用之前不为 0

先修改后端获取方式,代码更改如下:

File file = new File(uploadAbsolutePath);

if (!file.exists() && !file.mkdirs()) {

// 如果file对象不存在,那么就将该对象的路径名中不存在的文件夹目录建立出来

}

// 文件扩展名

String fileExt = name.substring(name.lastIndexOf(".") + 1).toLowerCase();

// 文件的绝对路径File

File uploadFile = new File(uploadAbsolutePath + "/" + newName);

try {

// 将上传的图片二进制流保存为文件

FileCopyUtils.copy(request.getInputStream(), new FileOutputStream(uploadFile));

} catch (IOException ioException) {

logger.error("图片保存到文件夹中出错!", ioException);

} catch (Exception e) {

logger.error("文件没有复制到指定的目录下" ,e);

}

此时后端就能够获取前端上传的图片了,ios 机型(iPhone 6s)依然没问题,安卓上传png格式的图片没有任何问题,但是jpg依然无法上传。在后端的时候,打印 request 的 headers,发现安卓机型上传jpg图片是会丢失 content-type,值为空。结合 issues 中的判断,也许是安卓机型在压缩 jpg 格式图片时出了问题,先解决再试试看!

第二步:加上androidpatch

根据官方说明,使用 webuploader.custom.js,其中将 runtime/html5/androidpatch.js 打包了进来。

然后在没有修改任何代码的情况下,经过五个手机的测试,新老机型:华为荣耀、魅蓝、联想等等的测试,安卓机可以在微信中随意上传图片了。这是个大坑啊!说明无法上传 jpg 格式图片的原因竟是压缩 jpg 格式图片的时候出错,导致进度条卡死,上传失败。

总结使用心得

按照以上的总结,我想下一次我应该能再一次利用这一次的经验解决微信上传图片的坑了~也懂得从request 的 headers 中寻找 bug 发生的原因,WebUploader 是个很优秀的开源插件,源码也写的很有条理,清晰易读,虽然我并没有读完。现在阅读框架源码是越来越轻松了,加油,下个目标是正在学习的 React.js。

以上所述是小编给大家介绍的Android 开发 使用WebUploader解决安卓微信浏览器上传图片中遇到的bug,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

android 浏览器上传图片,Android 开发 使用WebUploader解决安卓微信浏览器上传图片中遇到的bug...相关推荐

  1. Android上传文件到服务器500,使用WebUploader解决安卓微信浏览器上传图片中遇到的bug...

    摘自个人博客:走啊走的记录,欢迎点击查看,效果更佳! 微信浏览器上传图片bug的原因 微信在新版本中采用的是自己的X5内核浏览器,而在较老的版本中还有可能是安卓的原生浏览器.具体的环境我也不太了解,但 ...

  2. 使用WebUploader解决安卓微信浏览器上传图片中遇到的bug

    微信浏览器上传图片bug的原因 微信在新版本中采用的是自己的X5内核浏览器,而在较老的版本中还有可能是安卓的原生浏览器.具体的环境我也不太了解,但是经过实际多台安卓机型的测试,我采取的方案可以基本确保 ...

  3. 解决安卓微信浏览器中location.reload 或者 location.href失效的问题

    解决安卓微信浏览器中location.reload 或者 location.href失效的问题 参考文章: (1)解决安卓微信浏览器中location.reload 或者 location.href失 ...

  4. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )

    文章目录 前言 一.等待远程进程 mmap 函数执行完毕 二.从寄存器中获取进程返回值 三.博客资源 前言 前置博客 : [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | ...

  5. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  6. 安卓(android)建立项目时失败,出现Android Manifest.xml file missing几种解决方法?(总结中)

    安卓(android)建立项目时失败,出现Android Manifest.xml file missing几种解决方法?(总结中) 参考文章: (1)安卓(android)建立项目时失败,出现And ...

  7. 解决ios微信浏览器时间不兼容的问题

    解决ios微信浏览器时间格式不兼容的问题 由于ios在微信浏览器中无法识别"YYYY-MM-DD HH:MM:SS"格式的数据,所以在ios中页面将时间格式转换为"YYY ...

  8. 微信浏览器video标签没有封面_video 标签在微信浏览器的问题解决方法

    最近做的些web页面,内嵌许多小视频,在ios和安卓手机上播放时,遇到不少问题: 在微信浏览器内播放时,视频会自动全屏 解决办法: 给video标签加一些属性,调用h5原生video,我写了个例子,加 ...

  9. 安卓微信浏览器使用input file图片上传无法触发change事件

    问题现象 项目中遇到一个上传图片的功能,使用了file作为选择上传,需要做图片预览等功能.在多方测试后没有问题,但在安卓微信浏览器中却发现change事件失效无法触发. 解决办法 由于在项目中我是用来 ...

  10. 安卓微信浏览器无法支持input multiple的h5属性多图上传

    H5手机端 实现多图上传的功能 但是实际上 安卓手机上只能义词上传一张图片(测试的机型:小米)代码如下: 在微信开发中遇见一个问题 应用上传插件安卓手机无法进行多张上传 当时现象: 微信浏览器选择安卓 ...

最新文章

  1. Nginx重定向到子目录问题
  2. MAT之NSL:CPK_NN神经网络实现预测哪个样本与哪个样本处在同一层,从而科学规避我国煤矿突水灾难
  3. Jenkins中安装Credentials Binding插件时提示:Failed to load: SSH Credentials Plugin (1.18.2),Jenkins(2.282)or
  4. RMAN 备份与恢复 实例
  5. 和虫师一起学python(7)
  6. 前端学习(1155):常量const03
  7. 领域应用 | 小米在知识表示学习的探索与实践
  8. vs.net各版本解决方案相互转换工具
  9. 比较好用的python编译器_比酷传播
  10. mysql隐藏information_如何让普通用户登录phpmyadmin不显示information_schema
  11. ReactHooks——react-countdown倒计时——dayjs结合react-countdown
  12. 数字孪生--thingjs
  13. 浙江大学求是科学班计算机,浙江大学竺可桢学院求是科学班、智慧能源班、公共管理英才班2018年招生简章...
  14. 解读用巨象指纹浏览器进行引流的4种操作手法
  15. Windows 10 build Error !include: could not find: ****StdUtils.nsh
  16. 微信分享解决wx not defined
  17. VENC 通道属性配置参数理解
  18. 心得分享——c语言如何将多个字符串赋值给字符串数组(即c语言如何输入并储存多个字符串)
  19. oracle 存储过程语法例子
  20. hfs2.3中文版快速搭建http文件下载服务器系统——墨涩网

热门文章

  1. python求列表的方差值
  2. python制作卡通表情包_python——简单生成表情包
  3. python控制电脑休眠唤醒键_使用Python实现Wake On Lan远程开机功能
  4. Python利用wakeonlan库 局域网 网络唤醒电脑
  5. [Ant]Note of develop java with Ant
  6. electron 读取文件夹内容_读写本地文件
  7. ansible常见模块
  8. 打印机 计算机 usb,来古计算机-打印机端口自动识别成 USB大容量存储设备(USB mass storage device)...
  9. cisco路由器设置时间同步
  10. c语言程序编程实践总结,c语言编程实习心得