关于安卓手机微信浏览器中使用XMLHttpRequest 2上传图片显示字节数为0的解决办法

网友投稿 385 2023-07-17


关于安卓手机微信浏览器中使用XMLHttpRequest 2上传图片显示字节数为0的解决办法

前端js中使用XMLHttpRequest 2上传图片到服务器,PC端和大部分手机上都正常,但在少部分安卓手机上上传失败,服务器上查看图片,显示字节数为0。下面是上传图片的核心代码:

HTML

javascript

var filechooser = document.getElementById("choose");

filechooser.onchange = function () {

var _this = $(this);

if (!this.files.length) return;

var files = Array.prototype.slice.call(this.files);

if (files.length > 1) {

alert("一次只能上传1张图片");

return;

}

files.forEach(function (file, i) {

if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return;

var reader = new FileReader();

reader.onload = function () {

var result = this.result;

upload(result, file.type);

};

reader.readAsDataURL(file);

});

};

function upload(basestr, type){

var xhr = new XMLHttpRequest();

var text = window.atob(basestr.skQwPpFxQBKplit(",")[1]);

var bufhttp://fer = new Uint8Array(text.length);

var pecent = 0;

for (var i = 0; i < text.length; i++) {

buffer[i] = text.charCodeAt(i);

}

var blob = getBlob(buffer, type);

var formdata = new FormData();

formdata.append('imagefile', blob);

xhr.open('post', '/uploadtest');

xhr.onreadystatechange = function () {

if (xhr.readyState == 4 && xhr.status == 200) {

var jsonData = JSON.parse(xhr.responseText);

console.log(jsonData);

}

};

//利用progress事件显示数据发送进度

xhr.upload.addEventListener('progress', function (e) {

pecent = ~~(100 * e.loaded / e.total) / 2;

// 利用pecent来显示上传进度

}, false);

xhr.send(formdata);

}

function getBlob(buffer, format){

var Builder = window.WebKitBlobBuilder || window.MozBlobBuilder;

if(Builder){

var builder = new Builder();

builder.append(buffer);

return builder.getBlob(format);

} else {

return new window.Blob([ buffer ], {type: format});

}

}

上述代码使用FormData来实现表单数据提交。FormData是一种针对XHR2设计的新型数据类型,使用它我们可以很方便地实时以javaScript创建HTML

然后我们在服务端接收并保存图片,并返回已上传的图片的信息。

下面是Node.js代码的示例:

var Q = require('q');

var fs = require('fs');

var path = require('path');

var formidable = require('formidable');

var moment = require('moment');var imageUpload = function (){ };

imageUpload.prototype.useFormParseCallback = function(req){

var deferred = Q.defer();

var form = new formidable.IncomingForm();

form.parse(req, deferred.makeNodeResolver());

return deferred.promise;

};

imageUpload.prototype.uploadImageTest = function(req){

var pathName = 'uploadImgs/dealInfo/';

var uploadPath = path.join(__dirname, '../../public/', pathName);

return this.useFormParseCallback(req).then(function(files){

var file = files[1].imagefile;

var fileType = files[1].imagefile.type.split('/')[1];

var newFileName = 'upload_' + moment().format('x') + Math.random().toString().substr(2, 10) + '.' + fileType;

var readStream = fs.createReadStream(file.path);

var writeStream = fs.createWriteStream(uploadPath + newFileName);

var deferred = Q.defer();

readStream.pipe(writeStream);

readStream.on('end', deferred.makeNodeResolver());

return deferred.promise.then(function() {

fs.unlinkSync(file.path);

return {

fileName: newFileName,

filePath: '/' + pathName + newFileName,

fileSize: file.size/1024 > 1024 ? (~~(10*file.size/1024/1024))/10 + "MB" : ~~(file.size/1024) + "KB"

};

});

});

};

module.exports = imageUpload;

我们使用formidable这个包来接收上传文件的数据,然后将文件保存到/public/uploadImgs/dealInfo目录下(假定已在express中将public设置为static的根目录),并将图片按照指定的规则重命名,以保证上传图片不会因为名称相同而被覆盖。另外,代码中使用Q来避免http://直接使用回调函数,以更好地对函数功能进行分离。

上面的代码在PC端浏览器以及大部分主流移动设备上都能正常工作,但是少部分android设备上却会出现上传的图片字节数为0的情况。具体的原因大家可以看下面几个网页中的描述:

就是说这个是Android的一个bug!

那如何解决呢?

其实从上面给出的页面中可以找到答案,就是我们得换一种文件上传方式。在XHR2中,除了以Blob的方式上传文件外,还可以ArrayBuffer的方式上传文件。

下面是修改之后的前端JavaScript代码:

var filechooser = document.getElementById("choose");

filechooser.onchange = function () {

var _this = $(this);

if (!this.files.length) return;

var files = Array.prototype.slice.call(this.files);

if (files.length > 1) {

alert("一次只能上传1张图片");

return;

}

files.forEach(function (file, i) {

if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return;

var reader = new FileReader();

reader.onload = function () {

var result = this.result;

upload(result, file.type);

};

reader.readAsDataURL(file);

});

};

function upload(basestr, type){

var xhr = new XMLHttpRequest();

var text = window.atob(basestr.split(",")[1]);

var buffer = new Uint8Array(text.length);

var pecent = 0;

for (var i = 0; i < text.length; i++) {

buffer[i] = text.charCodeAt(i);

}

xhr.open('post', '/uploadtest?filetype=' + type.split('/')[1]);

xhr.setRequestHeader('Content-Type', 'application/octet-stream');

xhr.onreadystatechange = function () {

if (xhr.readyState == 4 && xhr.status == 200) {

var jsonData = JSON.parse(xhr.http://responseText);

console.log(jsonData);

}

};

//利用progress事件显示数据发送进度

xhr.upload.addEventListener('progress', function (e) {

pecent = ~~(100 * e.loaded / e.total) / 2;

// 利用pecent来显示上传进度

}, false);

xhr.send(buffer.buffer); // 以ArrayBuffer的方式上传图片

}

我将有变化的地方加了高亮显示。以ArrayBuffer方式上传图片必须添加'application/octet-stream'的RequestHeader,否则服务器无法响应请求。另外,通过这种方式上传图片我们也无法从表单数据中获取到文件类型,可以将文件类型以query的方式传到服务器,然后服务器根据文件类型来生成对应的文件,以下是经过少量修改之后的服务器代码:

imageUpload.prototype.uploadImageTest = function(req){

var pathName = 'uploadImgs/dealInfo/';

var uploadPath = path.join(__dirname, '../../public/', pathName);

return this.useFormParseCallback(req).then(function(files){

var file = files[1].file;

var fileType = req.query.filetype ? ('.' + req.query.filetype) : '.png';

var newFileName = 'upload_' + moment().format('x') + Math.random().toString().substr(2, 10) + '.' + fileType;

var readStream = fs.createReadStream(file.path);

var writeStream = fs.createWriteStream(uploadPath + newFileName);

var deferred = Q.defer();

readStream.pipe(writeStream);

readStream.on('end', deferred.makeNodeResolver());

return deferred.promise.then(function() {

fs.unlinkSync(file.path);

return {

fileName: newFileName,

filePath: '/' + pathName + newFileName,

fileSize: file.size/1024 > 1024 ? (~~(10*file.size/1024/1024))/10 + "MB" : ~~(file.size/1024) + "KB"

};

});

});

};

修改之后的代码可以支持Android手机,包括微信浏览器。注意不是所有的Android手机都会存在该问题,如果你发现在Andriod手机上无法上传图片,尤其是在微信浏览器中,则可以尝试下上面的方法。

以上所述是给大家介绍的关于安卓手机微信浏览器中使用XMLHttpRequest 2上传图片显示字节数为0的解决办法,希望对大家有所帮助!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java 并发编程学习笔记之Synchronized底层优化
下一篇:Bootstrap3 input输入框插入glyphicon图标的方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~