Sto*_*ive 270 javascript html5 webkit
我一直在尝试重新实现像Mozilla Hacks网站上的 HTML5图像上传器,但它适用于WebKit浏览器.部分任务是从canvas对象中提取图像文件并将其附加到FormData对象以进行上载.
问题是虽然canvas具有toDataURL返回图像文件表示的函数,但FormData对象仅接受来自File API的 File或Blob对象.
Mozilla解决方案使用以下仅限Firefox的功能canvas:
var file = canvas.mozGetAsFile("foo.png");
Run Code Online (Sandbox Code Playgroud)
...在WebKit浏览器上不可用.我能想到的最好的解决方案是找到一种方法将数据URI转换为File对象,我认为它可能是File API的一部分,但我不能为我的生活找到一些东西.
可能吗?如果没有,任何替代方案?
谢谢.
Sto*_*ive 455
在玩了几件事之后,我设法自己解决了这个问题.
首先,这会将dataURI转换为Blob:
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
Run Code Online (Sandbox Code Playgroud)
从那里,将数据附加到表单以便将其作为文件上载很容易:
var dataURL = canvas.toDataURL('image/jpeg', 0.5);
var blob = dataURItoBlob(dataURL);
var fd = new FormData(document.forms[0]);
fd.append("canvasImage", blob);
Run Code Online (Sandbox Code Playgroud)
小智 141
现在不推荐使用BlobBuilder和ArrayBuffer,这是使用Blob构造函数更新的顶级注释代码:
function dataURItoBlob(dataURI) {
var binary = atob(dataURI.split(',')[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'});
}
Run Code Online (Sandbox Code Playgroud)
Wil*_* T. 52
这个适用于iOS和Safari.
你需要使用Stoive的ArrayBuffer解决方案,但你不能像vava720那样使用BlobBuilder,所以这里是两者的混搭.
function dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: 'image/jpeg' });
}
Run Code Online (Sandbox Code Playgroud)
cui*_*ing 25
Firefox有canvas.toBlob()和canvas.mozGetAsFile()方法.
但其他浏览器则没有.
我们可以从canvas获取dataurl,然后将dataurl转换为blob对象.
这是我的dataURLtoBlob()功能.它很短.
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
Run Code Online (Sandbox Code Playgroud)
将此函数与FormData一起使用来处理画布或dataurl.
例如:
var dataurl = canvas.toDataURL('image/jpeg',0.8);
var blob = dataURLtoBlob(dataurl);
var fd = new FormData();
fd.append("myFile", blob, "thumb.jpg");
Run Code Online (Sandbox Code Playgroud)
此外,您可以HTMLCanvasElement.prototype.toBlob为非gecko引擎浏览器创建方法.
if(!HTMLCanvasElement.prototype.toBlob){
HTMLCanvasElement.prototype.toBlob = function(callback, type, encoderOptions){
var dataurl = this.toDataURL(type, encoderOptions);
var bstr = atob(dataurl.split(',')[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
var blob = new Blob([u8arr], {type: type});
callback.call(this, blob);
};
}
Run Code Online (Sandbox Code Playgroud)
现在canvas.toBlob()适用于所有现代浏览器,不仅适用于Firefox.例如:
canvas.toBlob(
function(blob){
var fd = new FormData();
fd.append("myFile", blob, "thumb.jpg");
//continue do something...
},
'image/jpeg',
0.8
);
Run Code Online (Sandbox Code Playgroud)
End*_*ess 22
我首选的方法是canvas.toBlob()
但无论如何这里是使用fetch ^^将base64转换为blob的另一种方法,
var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
fetch(url)
.then(res => res.blob())
.then(blob => {
var fd = new FormData()
fd.append('image', blob, 'filename')
console.log(blob)
// Upload
// fetch('upload', {method: 'POST', body: fd})
})Run Code Online (Sandbox Code Playgroud)
Mim*_*imo 19
感谢@Stoive和@ vava720,我以这种方式结合了两者,避免使用已弃用的BlobBuilder和ArrayBuffer
function dataURItoBlob(dataURI) {
'use strict'
var byteString,
mimestring
if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
byteString = atob(dataURI.split(',')[1])
} else {
byteString = decodeURI(dataURI.split(',')[1])
}
mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]
var content = new Array();
for (var i = 0; i < byteString.length; i++) {
content[i] = byteString.charCodeAt(i)
}
return new Blob([new Uint8Array(content)], {type: mimestring});
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*sco 12
不断发展的标准看起来像是canvas.toBlob()而不是像Mozilla一样猜测的canvas.getAsFile().
我没有看到任何支持它的浏览器:(
谢谢你这个伟大的线程!
此外,任何尝试接受答案的人都应该小心使用BlobBuilder,因为我发现支持受到限制(和命名空间):
var bb;
try {
bb = new BlobBuilder();
} catch(e) {
try {
bb = new WebKitBlobBuilder();
} catch(e) {
bb = new MozBlobBuilder();
}
}
Run Code Online (Sandbox Code Playgroud)
你在BlobBuilder上使用另一个库的polyfill吗?
这是Stoive 答案的 ES6 版本:
export class ImageDataConverter {
constructor(dataURI) {
this.dataURI = dataURI;
}
getByteString() {
let byteString;
if (this.dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(this.dataURI.split(',')[1]);
} else {
byteString = decodeURI(this.dataURI.split(',')[1]);
}
return byteString;
}
getMimeString() {
return this.dataURI.split(',')[0].split(':')[1].split(';')[0];
}
convertToTypedArray() {
let byteString = this.getByteString();
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return ia;
}
dataURItoBlob() {
let mimeString = this.getMimeString();
let intArray = this.convertToTypedArray();
return new Blob([intArray], {type: mimeString});
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
const dataURL = canvas.toDataURL('image/jpeg', 0.5);
const blob = new ImageDataConverter(dataURL).dataURItoBlob();
let fd = new FormData(document.forms[0]);
fd.append("canvasImage", blob);
Run Code Online (Sandbox Code Playgroud)
var BlobBuilder = (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder);
Run Code Online (Sandbox Code Playgroud)
可以在没有try catch的情况下使用.
感谢check_ca.做得好.
通过更改最后一行以适应 Blob,可以轻松修复 Stoive 的原始答案:
function dataURItoBlob (dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
return new Blob([ab],{type: mimeString});
}
Run Code Online (Sandbox Code Playgroud)
谢谢!@steovi 这个解决方案。
我添加了对 ES6 版本的支持,并从 unescape 更改为 dataURI(unescape 已弃用)。
converterDataURItoBlob(dataURI) {
let byteString;
let mimeString;
let ia;
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = encodeURI(dataURI.split(',')[1]);
}
// separate out the mime component
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
228299 次 |
| 最近记录: |