如何上传/ POST多个canvas元素

时间:2011-10-10 12:08:21

标签: javascript ajax json html5 html5-canvas

我必须为将来的项目(无闪光灯,IE10 +,FF7 +等)创建一个图像上传器,它在客户端而不是服务器上进行图像大小调整/转换/裁剪。

所以我创建了一个javascript界面​​,用户可以“上传”他们的文件并直接在浏览器中调整大小/裁剪,而无需联系服务器。性能还可以,不是那么好,但它确实有效。

endresult是一个canvas元素数组。用户可以在调整大小后编辑/裁剪图像,因此我将它们保留为画布而不是将它们转换为jpeg。 (这将使初始表现恶化)

现在这很好用,但我不知道现在将完成的canvas元素实际上传到服务器的最佳方法是什么。 (在服务器上使用asp.net 4通用处理程序)

我尝试从包含每个画布的dataurl的所有元素创建一个json对象。

问题是,当我得到10-40张图片时,浏览器会在创建dataurls时开始冻结,特别是对于大于2兆字节的图片。

            //images = array of UploadImage
            for (var i = 0; i < images.length; i++) {
                var data = document.getElementById('cv_' + i).toDataURL('image/jpg');
                images[i].data = data.substr(data.indexOf('base64') + 7);
            }

同样将它们转换为json对象(我​​使用的是json2.js)通常会导致我的浏览器崩溃。 (FF7)

我的对象

    var UploadImage = function (pFileName, pName, pDescription) {
        this.FileName = pFileName;
        this.Name = pName;
        this.Description = pDescription;
        this.data = null;
    }

上传例程

            //images = array of UploadImage
            for (var i = 0; i < images.length; i++) {
                var data = document.getElementById('cv_' + i).toDataURL('image/jpg');
                images[i].data = data.substr(data.indexOf('base64') + 7);
            }

            var xhr, provider;
            xhr = jQuery.ajaxSettings.xhr();
            if (xhr.upload) {
                xhr.upload.addEventListener('progress', function (e) {
                    console.log(Math.round((e.loaded * 100) / e.total) + '% done');
                }, false);
            }
            provider = function () {
                return xhr;
            };
            var ddd = JSON.stringify(images); //usually crash here
            $.ajax({
                type: 'POST',
                url: 'upload.ashx',
                xhr: provider,
                dataType: 'json',
                success: function (data) {
                    alert('ajax success: data = ' + data);
                },
                error: function () {
                    alert('ajax error');
                },
                data: ddd
            });

将canvas元素发送到服务器的最佳方法是什么?

我应该一次性发送还是逐个发送它们?

1 个答案:

答案 0 :(得分:5)

逐个上传文件会更好。需要更少的内存,只要一个文件准备好上传,就可以启动上传,而不是等待所有文件都准备好。

使用FormData发送文件。允许以二进制格式而不是base64编码上传文件。

var formData = new FormData;

如果Firefox使用canvas.mozGetAsFile('image.jpg')而不是canvas.toDataUrl()。允许避免从base64到二进制的不必要的转换。

var file = canvas.mozGetAsFile('image.jpg');
formData.append(file);

在Chrome中,使用BlobBuilder将base64转换为blob(请参阅dataURItoBlob函数

接受 在玩了几件事之后,我设法自己解决了这个问题。

首先,这会将dataURI转换为Blob:

//added for quick reference
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});
}

来自this question):

var blob = dataURItoBlob(canvas.toDataURL('image/jpg'));
formData.append(blob);

然后发送formData对象。我不确定如何在jQuery中执行它,但是使用普通的xhr对象就像这样:

var xhr = new XMLHttpRequest;
xhr.open('POST', 'upload.ashx', false);
xhr.send(formData);

在服务器上,您可以从Files集合中获取文件:

context.Request.Files[0].SaveAs(...);