我一直在尝试重新实现一个HTML5图像上传器,就像Mozilla Hacks网站上的那个,但它适用于WebKit浏览器。该任务的一部分是从canvas对象中提取图像文件,并将其附加到FormData对象中以便上传。

问题是,虽然canvas有toDataURL函数来返回图像文件的表示,但FormData对象只接受file API中的file或Blob对象。

Mozilla解决方案在画布上使用了以下仅限firefox的功能:

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

...这在WebKit浏览器上是不可用的。我能想到的最佳解决方案是找到某种方法将Data URI转换为File对象,我认为这可能是File API的一部分,但我无法找到这样做的方法。

这可能吗?如果没有,有什么替代方案吗?


当前回答

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

其他回答

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

toDataURL给你一个字符串,你可以把这个字符串放到一个隐藏的输入中。

在摆弄了一些东西之后,我自己设法弄明白了这一点。

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

从那里,将数据追加到表单,以便将其作为文件上传是很容易的:

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

可以在没有try捕获的情况下使用。

感谢check_ca。伟大的工作。

解析: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;
}