将数据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)});