如何上传/发布多个画布元素

发布于 2024-12-09 10:25:11 字数 2265 浏览 1 评论 0原文

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

因此,我制作了一个 JavaScript 界面,用户可以在其中“上传”他们的文件并直接在浏览器中调整大小/裁剪,而无需联系服务器。性能还可以,不是那么好,但是可以用。

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

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

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

问题是,当我获得 10-40 张图片时,浏览器在创建 dataurl 时开始冻结,尤其是对于大于 2 MB 的图像。

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

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

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

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.

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.

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)

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)

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

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

Also converting them to a json object (I am using json2.js) usually crashes my browser. (FF7)

My object

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

The upload routine

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

海之角 2024-12-16 10:25:11

文件一一上传效果更好。需要更少的内存,一旦一个文件准备好上传,就可以开始上传,而不是等待所有文件都准备好。

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

来自 这个问题):

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

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

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

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.

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

var formData = new FormData;

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

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.

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

From this question):

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

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

On server you can get files from Files collection:

context.Request.Files[0].SaveAs(...);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文