将数据URI转换为文件,然后附加到FormData

我一直在尝试重新实现一个像Mozilla Hacks站点上的 HTML5图片上传器,但是它可以和WebKit浏览器一起工作。 部分任务是从canvas对象中提取图像文件,并将其附加到FormData对象上传。

问题是,尽pipecanvas具有toDataURL函数来返回图像文件的表示,但FormData对象只接受来自File API的 File或Blob对象。

Mozilla解决scheme在canvas上使用了以下仅限Firefox的function:

 var file = canvas.mozGetAsFile("foo.png"); 

…在WebKit浏览器上不可用。 我能想到的最好的解决scheme是find一种方法将数据URI转换为File对象,我认为这可能是File API的一部分,但是我不能为了我的生活find一些可以做到的事情。

可能吗? 如果没有,还有其他的select

谢谢。

在玩了几件事之后,我设法自己弄清楚了这一点。

首先,这会将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}); } 

从那里,将数据附加到一个表格,以便将其作为file upload很容易:

 var dataURL = canvas.toDataURL('image/jpeg', 0.5); var blob = dataURItoBlob(dataURL); var fd = new FormData(document.forms[0]); fd.append("canvasImage", blob); 

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'}); } 

这个可以在iOS和Safari中使用。

你需要使用Stoive的ArrayBuffer解决scheme,但是你不能使用BlobBuilder,因为vava720表示,所以这里是两者的混搭。

 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' }); } 

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}); } 

在FormData中使用这个函数来处理你的canvas或dataurl。

例如:

 var dataurl = canvas.toDataURL('image/jpeg',0.8); var blob = dataURLtoBlob(dataurl); var fd = new FormData(); fd.append("myFile", blob, "thumb.jpg"); 

另外,您可以为非壁虎引擎浏览器创build一个HTMLCanvasElement.prototype.toBlob方法。

 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); }; } 

现在canvas.toBlob()适用于所有现代浏览器,不仅仅是firefox。 例如:

 canvas.toBlob( function(blob){ var fd = new FormData(); fd.append("myFile", blob, "thumb.jpg"); //continue do something... }, 'image/jpeg', 0.8 ); 

感谢@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}); } 

不断发展的标准看起来像canvas.toBlob()而不是canvas.getAsFile()作为Mozilla hazarded猜测。

我没有看到任何浏览器还支持:(

感谢这个伟大的线程!

此外,任何人试图接受的答案应小心BlobBuilder,因为我发现支持是有限的(和命名空间):

  var bb; try { bb = new BlobBuilder(); } catch(e) { try { bb = new WebKitBlobBuilder(); } catch(e) { bb = new MozBlobBuilder(); } } 

你是否在BlobBuilder中使用另一个库的polyfill?

我最喜欢的方式是canvas.toBlob()

但无论如何,这里是另一种方式来转换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}) }) 
 var BlobBuilder = (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder); 

可以使用没有尝试捕获。

Thankx check_ca。 做得好。

Stoive的原始答案很容易通过更改最后一行来容纳Blob来解决:

 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}); } 

这是一个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}); } } 

用法:

 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); 

使其简单:D

 function dataURItoBlob(dataURI,mime) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs var byteString = window.atob(dataURI); // separate out the mime component // write the bytes of the string to an ArrayBuffer //var ab = new ArrayBuffer(byteString.length); var ia = new Uint8Array(byteString.length); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } // write the ArrayBuffer to a blob, and you're done var blob = new Blob([ia], { type: mime }); return blob; } 

toDataURL给你一个string,你可以把这个string放到一个隐藏的input中。

我和Ravinder Payal有完全一样的问题,我find了答案。 尝试这个:

 var dataURL = canvas.toDataURL("image/jpeg"); var name = "image.jpg"; var parseFile = new Parse.File(name, {base64: dataURL.substring(23)});