标题 | 如何在移动web上上传文件.. |
内容 | xmlhttprequest2.0 可以支持文件上传.这东东很方便,但是在实际使用中碰到了一些问题.这里记录下. 正常情况下我们是这样生成2进制文件的. //data为文件的base64编码 function dataURLtoBlob(data) { var tmp = data.split(','); tmp[1] = tmp[1].replace(/s/g,''); var binary = atob(tmp[1]); var array = []; for(var i = 0; i < binary.length; i++) { array.push(binary.charCodeAt(i)); } return new Blob([new Uint8Array(array)], {type: 'image/jpeg'}); } 但是在android手机上可能会由于没有blob对象导致无法生成blob.怎么办捏.可以使用以下代码: function newBlob(data, datatype){ var out; try { out = new Blob([data], {type: datatype}); //一切正常,直接使用blob. } catch (e) { window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; if (e.name == 'TypeError' && window.BlobBuilder) { var bb = new BlobBuilder(); bb.append(data.buffer); out = bb.getBlob(datatype); //还可以抢救一下..使用blobbuilder来生成文件.. } else { //没救了,放弃治疗. } } return out; } ok.现在文件已经ready了. 我们创建一个formadata var file = dataURLtoBlob(img); fd.append('img',file); 愉快的上传….然后…然后…没有然后了…抓包看下. ------WebKitFormBoundarysToAVAYMLPFfJF96 Content-Disposition: form-data; name="img"; filename="blob" Content-Type: application/octet-stream ------WebKitFormBoundarysToAVAYMLPFfJF96-- 文件的内容呢… 好吧..既然没法愉快用formdata..那么就自己动手生成一个post的包体吧…下面是相关的代码.. function FormDataShim () { var o = this, parts = [],// Data to be sent boundary = Array(5).join('-') + (+new Date() * (1e16*Math.random())).toString(32), oldSend = XMLHttpRequest.prototype.send; this.append = function (name, value, filename) { parts.push('--' + boundary + 'rnContent-Disposition: form-data; name="' + name + '"'); if (value instanceof Blob) { parts.push('; filename="'+ (filename || 'blob') +'"rnContent-Type: ' + value.type + 'rnrn'); parts.push(value); } else { parts.push('rnrn' + value); } parts.push('rn'); }; //把xhr的send方法重写一下. XMLHttpRequest.prototype.send = function (val) { var fr, data, oXHR = this; if (val === o) { // 最后加一下boundary..注意这里一定要在最后加rn..否则服务器有可能会解析参数失败.. parts.push('--' + boundary + '--rn'); data = new XBlob(parts); fr = new FileReader(); fr.onload = function () { oldSend.call(oXHR, fr.result); }; fr.onerror = function (err) { throw err; }; fr.readAsArrayBuffer(data); // 设置content-type this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); XMLHttpRequest.prototype.send = oldSend; } else { oldSend.call(this, val); } }; } 最后完整的代码长这样. function newBlob(data, datatype){ var out; try { out = new Blob([data], {type: datatype}); } catch (e) { window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; if (e.name == 'TypeError' && window.BlobBuilder) { var bb = new BlobBuilder(); bb.append(data.buffer); out = bb.getBlob(datatype); } else if (e.name == "InvalidStateError") { out = new Blob([data], {type: datatype}); } else { } } return out; } // 判断是否需要blobbuilder var needsFormDataShim = (function () { var bCheck = ~navigator.userAgent.indexOf('Android') && ~navigator.vendor.indexOf('Google') && !~navigator.userAgent.indexOf('Chrome'); return bCheck && navigator.userAgent.match(/AppleWebKit/(d+)/).pop() <= 534; })(), blobConstruct = !!(function () { try { return new Blob(); } catch (e) {} })(), XBlob = blobConstruct ? window.Blob : function (parts, opts) { var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder); parts.forEach(function (p) { bb.append(p); }); return bb.getBlob(opts ? opts.type : undefined); }; function FormDataShim () { // Store a reference to this var o = this, parts = [],// Data to be sent boundary = Array(5).join('-') + (+new Date() * (1e16*Math.random())).toString(32), oldSend = XMLHttpRequest.prototype.send; this.append = function (name, value, filename) { parts.push('--' + boundary + 'rnContent-Disposition: form-data; name="' + name + '"'); if (value instanceof Blob) { parts.push('; filename="'+ (filename || 'blob') +'"rnContent-Type: ' + value.type + 'rnrn'); parts.push(value); } else { parts.push('rnrn' + value); } parts.push('rn'); }; // Override XHR send() XMLHttpRequest.prototype.send = function (val) { var fr, data, oXHR = this; if (val === o) { //注意不能漏最后的rn ,否则有可能服务器解析不到参数. parts.push('--' + boundary + '--rn'); data = new XBlob(parts); fr = new FileReader(); fr.onload = function () { oldSend.call(oXHR, fr.result); }; fr.onerror = function (err) { throw err; }; fr.readAsArrayBuffer(data); this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); XMLHttpRequest.prototype.send = oldSend; } else { oldSend.call(this, val); } }; } //把图片转成formdata 可以使用的数据... //这里要把s替换掉..要不然atob的时候会出错.... function dataURLtoBlob(data) { var tmp = data.split(','); tmp[1] = tmp[1].replace(/s/g,''); var binary = atob(tmp[1]); var array = []; for(var i = 0; i < binary.length; i++) { array.push(binary.charCodeAt(i)); } return new newBlob(new Uint8Array(array), 'image/jpeg'); } function uploadFile(img){ var fd = needsFormDataShim ? new FormDataShim() : new FormData(); var file = dataURLtoBlob(img); fd.append('img',file); var prog = function(e){ /*你的逻辑*/ } var load = function(e){ /*你的逻辑*/ } var error = function(e){ /*你的逻辑*/ } var abort = function(e){ /*你的逻辑*/ } var xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress',prog,false); xhr.addEventListener('load',load,false); xhr.addEventListener('error',error,false); xhr.addEventListener('abort',abort,false); xhr.onreadystatechange = function(){ /*你的逻辑*/ } xhr.open('POST','/upload',true); xhr.send(fd); } |
随便看 |
|
在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。