我正在创建一个手机网站,可以调整照片大小和上传照片。
$('#ImgPreview canvas').each(function(pIndex) {
vFormData.append(pIndex, canvasToJpegBlob($(this)[0]), vIssueId +'-attachment0'+ pIndex +'.jpg');
});
$.ajax({
url: '/api/ob/issuefileupload',
data: vFormData,
processData: false,
contentType: false,
type: 'POST'
}).done(function(pData) {
window.location = '/issue?id='+ vIssueId;
}).fail(function(pJqXHR) {
alert(My.Strings.UploadFailed);
});
这适用于Android版Chrome和iOS版Safari,但在原生Android浏览器中,文件的内容长度为0,名称为Blob + UID。当文件添加到formdata时,大小似乎也相当大(900k反对Chrome中的50k)。
canvasToJpegBlob函数:
function canvasToJpegBlob(pCanvas) {
var vMimeType = "image/jpeg",
vDataURI,
vByteString,
vBlob,
vArrayBuffer,
vUint8Array, i,
vBlobBuilder;
vDataURI = pCanvas.toDataURL(vMimeType, 0.8);
vByteString = atob(vDataURI.split(',')[1]);
vArrayBuffer = new ArrayBuffer(vByteString.length);
vUint8Array = new Uint8Array(vArrayBuffer);
for (i = 0; i < vByteString.length; i++) {
vUint8Array[i] = vByteString.charCodeAt(i);
}
try {
vBlob = new Blob([vUint8Array.buffer], {type : vMimeType});
} catch(e) {
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name === 'TypeError' && window.BlobBuilder) {
vBlobBuilder = new BlobBuilder();
vBlobBuilder.append(vUint8Array.buffer);
vBlob = vBlobBuilder.getBlob(vMimeType);
} else if (e.name === 'InvalidStateError') {
vBlob = new Blob([vUint8Array.buffer], {type : vMimeType});
} else {
alert(My.Strings.UnsupportedFile);
}
}
return vBlob;
}
有没有办法在原生Android浏览器中使用它?
答案 0 :(得分:6)
我也遇到了这个问题,需要提出一个更通用的解决方案,因为在某些情况下我无法控制服务器端代码。
最终我找到了几乎完全透明的解决方案。方法是将损坏的FormData
填充为blob,以multipart/form-data
的必要格式附加数据。它覆盖了XHR的send()
,其版本将blob读入请求中发送的缓冲区。
这是主要代码:
var
// Android native browser uploads blobs as 0 bytes, so we need a test for that
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;
})(),
// Test for constructing of blobs using new Blob()
blobConstruct = !!(function () {
try { return new Blob(); } catch (e) {}
})(),
// Fallback to BlobBuilder (deprecated)
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 () {
var
// Store a reference to this
o = this,
// Data to be sent
parts = [],
// Boundary parameter for separating the multipart values
boundary = Array(21).join('-') + (+new Date() * (1e16*Math.random())).toString(36),
// Store the current XHR send method so we can safely override it
oldSend = XMLHttpRequest.prototype.send;
this.append = function (name, value, filename) {
parts.push('--' + boundary + '\nContent-Disposition: form-data; name="' + name + '"');
if (value instanceof Blob) {
parts.push('; filename="'+ (filename || 'blob') +'"\nContent-Type: ' + value.type + '\n\n');
parts.push(value);
}
else {
parts.push('\n\n' + value);
}
parts.push('\n');
};
// Override XHR send()
XMLHttpRequest.prototype.send = function (val) {
var fr,
data,
oXHR = this;
if (val === o) {
// Append the final boundary string
parts.push('--' + boundary + '--');
// Create the blob
data = new XBlob(parts);
// Set up and read the blob into an array to be sent
fr = new FileReader();
fr.onload = function () { oldSend.call(oXHR, fr.result); };
fr.onerror = function (err) { throw err; };
fr.readAsArrayBuffer(data);
// Set the multipart content type and boudary
this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
XMLHttpRequest.prototype.send = oldSend;
}
else {
oldSend.call(this, val);
}
};
}
只需像这样使用它,然后正常调用fd.append(name, value)
:
var fd = needsFormDataShim ? new FormDataShim() : new FormData();
答案 1 :(得分:1)
如何尝试在画布上绘制它,使用矩阵将其缩放到您希望的大小,然后使用canvas.toDataURL
将其发送到服务器。看看这个question。
答案 2 :(得分:1)
我用它来解决问题:
// not use blob, simply use key value
var form = new FormData();
// get you content type and raw data from data url
form.append( 'content_type', type);
form.append( 'content', raw);