Как загрузить / POST несколько элементов холста - PullRequest
7 голосов
/ 10 октября 2011

Мне нужно создать загрузчик изображений для будущего проекта (без флэш-памяти, IE10 +, FF7 + и т. Д.), Который выполняет изменение размера / преобразование / обрезку изображений на стороне клиента, а не на сервере.

Итак, я сделалинтерфейс javascript, в котором пользователь может «выгружать» свои файлы и получать размеры / обрезки в браузере напрямую, даже не обращаясь к серверу.Производительность нормальная, не очень хорошая, но она работает.

Конечным результатом является массив элементов canvas.Пользователь может редактировать / обрезать изображения после их изменения размера, поэтому я сохраняю их как холст вместо преобразования их в формат JPEG.(Что ухудшило бы начальную производительность)

Теперь это работает нормально, но я не знаю, как лучше всего загрузить готовые элементы canvas на сервер.(Использование универсального обработчика asp.net 4 на сервере)

Я попытался создать объект json из всех элементов, содержащих dataurl каждого холста.

Проблема в том, что когда я получил 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 Ответ

5 голосов
/ 10 октября 2011

Загрузка файлов по одному лучше.Требуется меньше памяти и, как только один файл готов к загрузке, загрузка может быть начата вместо ожидания, пока все файлы будут готовы.

Используйте 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 в блоб (см. dataURItoBlob function

принято После игры с несколькими вещамиМне удалось выяснить это сам.

Прежде всего, это преобразует 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);

На сервере вы можете получить файлы из коллекции Files:

context.Request.Files[0].SaveAs(...);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...