如何上传/发布多个画布元素 [英] How to upload/POST multiple canvas elements

查看:42
本文介绍了如何上传/发布多个画布元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have to create an image uploader for a future project (No flash, IE10+, FF7+ etc.) that does image resizing/converting/cropping on the clientside and not on the server.

所以我制作了一个 javascript 界面,用户可以在其中上传"他们的文件并直接在浏览器中调整大小/裁剪,而无需联系服务器.性能还可以,不是很好,但是可以.

So I made a javascript interface where the user can 'upload' their files and get resized/cropped in the browser directly, without ever contacting the server. The performance is OK, not that good, but it works.

最终结果是一组画布元素.用户可以在调整大小后编辑/裁剪图像,因此我将它们保留为画布而不是将它们转换为 jpeg.(这会恶化初始性能)

The endresult is an array of canvas elements. The user can edit/crop the images after they got resized, so I keep them as canvas instead of converting them to jpeg. (Which would worsen the initial performance)

现在这工作正常,但我不知道现在将完成的画布元素实际上传到服务器的最佳方式是什么.(在服务器上使用 asp.net 4 通用处理程序)

Now this works fine, but I don't know what's the best way to actually upload the finished canvas elements to the server now. (Using a asp.net 4 generic handler on the server)

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

I have tried creating a json object from all elements containing the dataurl of each canvas.

问题是,当我得到 10-40 张图片时,浏览器在创建 dataurl 时开始冻结,尤其是对于大于 2 兆字节的图片.

The problem is, when I got 10-40 pictures, the browser starts freezing when creating the dataurls, especially for images that are larger than 2 megabyte.

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

Also converting them to a json object (I am using json2.js) usually crashes my browser. (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
            });

将画布元素发送到服务器的最佳方式是什么?

What would be the best way to send the canvas elements to the server?

我应该一次全部发送还是一个一个发送?

Should I send them all at once or one by one?

推荐答案

文件一个一个上传比较好.需要更少的内存,只要一个文件准备好上传,就可以开始上传,而不是等待所有文件都准备好.

Uploading files one by one is better. Requires less memory and as soon as one file ready to upload, the upload can be started instead of waiting while all files will be prepared.

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

Use FormData to send files. Allows to upload files in binary format instead of base64 encoded.

var formData = new FormData;

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

If Firefox use canvas.mozGetAsFile('image.jpg') instead of canvas.toDataUrl(). Allow to avoid unnecessary conversion from base64 to binary.

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

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

In Chrome use BlobBuilder to convert base64 into blob (see dataURItoBlob function

接受在玩了一些东西之后,我自己设法解决了这个问题.

accepted After playing around with a few things, I managed to figure this out myself.

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

First of all, this will convert a dataURI to a 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});
}

来自这个问题):

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

然后发送 formData 对象.我不知道如何在 jQuery 中做到这一点,但使用普通的 xhr 对象就像这样:

And then send the formData object. I'm not sure how to do it in jQuery, but with plain xhr object it like so:

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

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

On server you can get files from Files collection:

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

这篇关于如何上传/发布多个画布元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆