2011-10-10 21 views
7

Tengo que crear un cargador de imágenes para un proyecto futuro (Sin flash, IE10 +, FF7 + etc.) que cambie el tamaño de imagen/conversión/recorte en el cliente y no en el servidor.Cómo cargar/POST múltiples elementos de lienzo

Así que hice una interfaz de JavaScript donde el usuario puede 'cargar' sus archivos y obtener el tamaño/recortar en el navegador directamente, sin tener que contactar al servidor. El rendimiento está bien, no tan bueno, pero funciona.

endresult es una matriz de elementos de lienzo. El usuario puede editar/recortar las imágenes una vez que se hayan redimensionado, por lo que las guardo como lienzo en lugar de convertirlas a jpeg. (Lo que empeoraría el rendimiento inicial)

Ahora esto funciona bien, pero no sé cuál es la mejor manera de cargar realmente los elementos de lienzo terminados al servidor ahora. (Usando un manipulador genérico asp.net 4 en el servidor)

He intentado crear un objeto json a partir de todos los elementos que contienen la columna de datos de cada lienzo.

El problema es que cuando obtuve 10-40 imágenes, el navegador comienza a congelarse al crear los dataurls, especialmente para imágenes que son más grandes que 2 megabytes.

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

también ellos convertir a un objeto JSON (estoy usando json2.js) por lo general se bloquea el navegador. (FF7)

Mi objetivo

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

La carga rutina

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

¿Cuál sería la mejor manera de enviar los elementos de la lona en el servidor?

¿Debo enviarlos todos a la vez o uno por uno?

+2

Esta es una pregunta muy interesante . No estoy seguro de por qué 2 downvotes sin ningún comentario, +1 –

+1

¿Por qué en el mundo se bajó esta pregunta? – Pointy

+0

Genera la url de datos y la envía de a uno a la vez. Esto reducirá el uso de memoria. También le permite mostrar el progreso (no se admite xhr2). La otra ventaja es que la lógica del servidor será un poco más fácil y el uso de memoria en el servidor será menor. – Gerben

Respuesta

5

Cargar archivos uno por uno es mejor. Requiere menos memoria y tan pronto como un archivo esté listo para cargarse, la carga se puede iniciar en lugar de esperar mientras se preparan todos los archivos.

Utilice FormData para enviar archivos. Permite cargar archivos en formato binario en lugar de codificación base64.

var formData = new FormData; 

Si Firefox utilizar canvas.mozGetAsFile ('imagen.jpg') en lugar de canvas.toDataURL(). Permitir evitar la conversión innecesaria de base64 a binario.

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

En Chrome utiliza para convertir BlobBuilder base 64 en la mancha (ver dataURItoBlob función

aceptadas Después de jugar un poco con algunas cosas, me las arreglé para resolver esto a mí mismo.

En primer lugar, esto va a convertir un DataURI a un 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}); 
} 

De this question):

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

Y a continuación, enviar el objeto formData. No estoy seguro de cómo hacerlo en jQuery, pero con xhr llano objeto que de este modo:

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

El servidor puede obtener los archivos de archivos de colección:

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

Esto está funcionando bien, gracias. – elch

Cuestiones relacionadas