xmlhttprequest2.0 可以支持文件上傳.這東東很方便,但是在實(shí)際使用中碰到了一些問題.這里記錄下.
正常情況下我們是這樣生成2進(jìn)制文件的.
//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手機(jī)上可能會由于沒有blob對象導(dǎo)致無法生成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.現(xiàn)在文件已經(jīng)ready了.
我們創(chuàng)建一個formadata
var file = dataURLtoBlob(img);
fd.append('img',file);
愉快的上傳….然后…然后…沒有然后了…抓包看下.
------WebKitFormBoundarysToAVAYMLPFfJF96
Content-Disposition: form-data; name="img"; filename="blob"
Content-Type: application/octet-stream
------WebKitFormBoundarysToAVAYMLPFfJF96--
文件的內(nèi)容呢…
好吧..既然沒法愉快用formdata..那么就自己動手生成一個post的包體吧…下面是相關(guān)的代碼..
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..否則服務(wù)器有可能會解析參數(shù)失敗..
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);
// 設(shè)置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 ,否則有可能服務(wù)器解析不到參數(shù).
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);
}
};
}
//把圖片轉(zhuǎn)成formdata 可以使用的數(shù)據(jù)...
//這里要把s替換掉..要不然atob的時(shí)候會出錯....
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);
}
更多信息請查看IT技術(shù)專欄