Ajax使用XMLHttpRequest上传Blob在Android下的BUG

案例背景

MBD要增加认证功能,要能够上传图片。

lz想偷懒用一个现成的js库来完成html5下带进度的上传控件,于是各种找。

发现一个这个:resumable.js

resumable.js

比其他几个类似 plupload轻量很多,纯粹只针对html5,完全满足移动端需要。果断采用。

能分块上传!能断点续传!能暂停继续!

好吧,lz很兴奋。

完成前端代码编写以后,就开始各种碰壁了……

第一次碰壁:

我们上传文件的保存用了YunStorage,但是,这个坑爹货上传的每个文件的位置都是随机的。要完成断点续传和分块上传,必须所有碎片文件放在一起。在现有架构下,根本无法保证上传的文件都在一个服务器上。除非做专门服务器设置更改,于是决定放弃这个功能,改为只用基本上传功能。

第二次碰壁:

lz手机是Android4.4版本,pc开发时候用Chrome进行模拟,开发工作一切正常,提交测试时候,测试发现安卓测试机除了Chrome浏览器外基本没有能够成功上传的……反倒是苹果设备一切正常。

查了一下服务器日志,上传的内容对比之下,安卓测试机提交的文件,所有信息都对,唯独,获取的上传文件是0kb!!!

同样的代码同样的环境换lz手机一切OK。排除服务器问题后,怀疑是上传组件的问题。艰难的换成了plupload之后,bug更多,测试机上甚至不能弹出文件选择界面,可能是版本问题,一些函数都无法找到。而且要额外加载的文件由压缩前28kb变成压缩后108kb。

决定换回之前的方案,排查问题所在。

 

问题排查

监视logcat日志,用测试机连接pc查看日志,在前端脚本中输出log。

排查后发现日志无问题,XMLHttpRequest对象在send前准备的数据正常,上传之前读取文件大小等信息全都正确。无解。

安装抓包工具,抓测试手机发往服务器的数据包,发现lz手机发包有大量payload数据。

js-android-bug-2

上传内容也确实有图片数据

js-android-bug-3

 

但是,测试机的数据却是这个样子:

js-android-bug-4 js-android-bug-5

 

直接就结束了!!!什么都没有发送!!!!

 

pc的Chrome调试下监测数据,FormData里面append了一个blob对象,这个对象就是上传的文件数据。

 

崩溃,度娘无解,没人问这个问题,谁也不知道。

这时候果断的找谷歌。

js-android-bug-6

 

我都还没敲完好吧,谷歌就知道了!!!!

然后很多人都在讨论,原来这个是Android系统的一个bug。

XMLHttpRequest在发送blob对象的时候,会发空文件,在4.0-4.1版本确实存在,不过后续没人讨论,据说4.2还是4.3就修复了。

有人提供了一个替代方案,用ArrayBuffer替代Blob传输文件,但是,但是,lz研究了一下发现这个方法好像不能传别的参数。因为直接把文件作为元数据post了。或者可以解决,但是改动成本太高。

尝试将ArrayBuffer数据转为Base64数据作为文本进行传输,结果发现js自定义方法转的base64数据,php接收后尝试解出再还原成文件过程中不知道哪里不对,总之就是无法实现。

 

然后,lz终于看见有人说了一句:不用Blob对象,用File对象就可以了,只是这样就不能分块了。

shuai

分毛块啊,服务器就不能分块了好吧!!!

就是因为分块才需要用Blob的好吧,Blob的slice()方法,将元数据切割形成新的Blob对象。

果断修改resumable.js的代码,增加了一段,如果设置块大小大于或等于文件大小,就不进行分块操作,直接把File对象传递给FormData。

然后,颤颤巍巍的点了一下上传。。。。。

0%

84%

上传成功……

if($.fileObjSize <= $.endByte){
    bytes = $.fileObj.file;
}

三行代码解决问题,追查bug用了2天……

 

总结

好吧,告诉一下小伙伴们,Android设备好多有bug,用XMLHttpRequest进行ajax上传文件的时候要知道不能用Blob对象。

我想对安卓的小伙伴们说,贵圈太乱,还是水果好……

 

参考信息

MDN – Web技术文档 – Web API 接口 – XMLHttpRequest

MDN – Web技术文档 – Web API 接口 – XMLHttpRequest – FormData

MDN – Web技术文档 – Web API 接口 – Blob

MDN – Web技术文档 – Web API 接口 – ArrayBuffer

Issue 39882: Browser: Trying to send a Blob with XHR2 sends the request with an empty body

发表评论

电子邮件地址不会被公开。 必填项已用*标注