2012-08-09 34 views
76

Estoy permitiendo que el usuario cargue imágenes en una página mediante la operación de arrastrar & y otros métodos. Cuando se descarta una imagen, estoy usando URL.createObjectURL para convertirla en una URL de objeto para mostrar la imagen. No estoy revocando la url, ya que la reutilizo.¿Cómo obtener un archivo o blob de una URL de objeto?

lo tanto, cuando llega el momento de crear un objeto FormData por lo que puede permitir que se cargue un formulario con una de esas imágenes en el mismo, ¿hay alguna manera puedo entonces revertir esa URL del objeto nuevo en una Blob o File por lo ¿Puedo agregarlo a un objeto FormData?

+0

No importa los dos comentarios anteriores: todo lo que debe hacer es enviar un 'XMLHttpRequest' a la URL del blob. – gengkev

+7

¡qué gran pregunta! –

+0

¿Por qué no simplemente almacenar los objetos del archivo original en algún lugar, luego usar el URL del objeto para mostrarlos y al enviar el formulario, usar los archivos originales? – user764754

Respuesta

52

Como gengkev alude a en su comentario anterior, parece que la mejor única manera/de hacerlo es con una llamada asincrónica XHR2:

var xhr = new XMLHttpRequest(); 
xhr.open('GET', 'blob:http%3A//your.blob.url.here', true); 
xhr.responseType = 'blob'; 
xhr.onload = function(e) { 
    if (this.status == 200) { 
    var myBlob = this.response; 
    // myBlob is now the blob that the object URL pointed to. 
    } 
}; 
xhr.send(); 
+14

No funciona en caso de solicitudes de dominio cruzado. –

+14

¿Cuándo tendrá alguna vez un * objectURL * que no sea local para el dominio y el alcance actuales? – BrianFreud

+4

lo hice igual que arriba, pero no obtuve 404 con el xhr. ¿que esta pasando? –

2

Si muestra el archivo en un lienzo de todas formas también puede convertir el contenido del lienzo a un objeto blob.

canvas.toBlob(function(my_file){ 
    //.toBlob is only implemented in > FF18 but there is a polyfill 
    //for other browsers https://github.com/blueimp/JavaScript-Canvas-to-Blob 
    var myBlob = (my_file); 
}) 
+1

Tenga en cuenta que eso realmente no le devuelve el * mismo * archivo original; está haciendo un nuevo archivo de imagen sobre la marcha. La última vez que lo probé hace un par de años, descubrí que, al menos en Chrome, el nuevo archivo de imagen no está comprimido: tenía 10k jpgs convirtiéndolo en 2.5 mb jpgs. – BrianFreud

0

Desafortunadamente @ respuesta de BrianFreud no se ajusta a mis necesidades, que tenía un poco de necesidad diferente , y sé que esa no es la respuesta para la pregunta de @ BrianFreud, pero lo dejo aquí porque muchas personas llegaron aquí con mi misma necesidad. Necesitaba algo como '¿Cómo obtener un archivo o blob de una URL?', Y la respuesta correcta actual no se ajusta a mis necesidades porque no es de dominio cruzado.

que tienen un sitio web que consume imágenes de un S3 Azure Storage/Amazonas, y hay que almacenar objetos nombrados con uniqueidentifiers:

de ejemplo: http: //****.blob.core.windows. net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf

Algunas de estas imágenes se deben descargar de la interfaz de nuestro sistema. Para evitar pasar este tráfico a través de mi servidor HTTP, ya que estos objetos no requieren acceso a seguridad (excepto por filtrado de dominio), decidí hacer una solicitud directa en el navegador del usuario y usar el procesamiento local para darle un nombre real al archivo y extensión

Para lograr eso he utilizado este gran artículo de Henry Algus: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1. Primer paso: Añadir soporte binario para jQuery

/** 
* 
* jquery.binarytransport.js 
* 
* @description. jQuery ajax transport for making binary data type requests. 
* @version 1.0 
* @author Henry Algus <[email protected]> 
* 
*/ 

// use this transport for "binary" data type 
$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) { 
    // check for conditions and support for blob/arraybuffer response type 
    if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) { 
     return { 
      // create new XMLHttpRequest 
      send: function (headers, callback) { 
       // setup all variables 
       var xhr = new XMLHttpRequest(), 
     url = options.url, 
     type = options.type, 
     async = options.async || true, 
     // blob or arraybuffer. Default is blob 
     dataType = options.responseType || "blob", 
     data = options.data || null, 
     username = options.username || null, 
     password = options.password || null; 

       xhr.addEventListener('load', function() { 
        var data = {}; 
        data[options.dataType] = xhr.response; 
        // make callback and send data 
        callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders()); 
       }); 

       xhr.open(type, url, async, username, password); 

       // setup custom headers 
       for (var i in headers) { 
        xhr.setRequestHeader(i, headers[i]); 
       } 

       xhr.responseType = dataType; 
       xhr.send(data); 
      }, 
      abort: function() { 
       jqXHR.abort(); 
      } 
     }; 
    } 
}); 

2. Segundo paso: Hacer una solicitar usando este tipo de transporte.

function downloadArt(url) 
{ 
    $.ajax(url, { 
     dataType: "binary", 
     processData: false 
    }).done(function (data) { 
     // just my logic to name/create files 
     var filename = url.substr(url.lastIndexOf('/') + 1) + '.png'; 
     var blob = new Blob([data], { type: 'image/png' }); 

     saveAs(blob, filename); 
    }); 
} 

Ahora puede utilizar el Blob creado como usted quiere, en mi caso quiero guardarlo en el disco.

3. Opcional: Guardar el archivo en el ordenador del usuario mediante FileSaver

he utilizado FileSaver.js guardar en el disco el archivo descargado, si usted necesita para lograr que, por favor use esta librería javascript:

https://github.com/eligrey/FileSaver.js/

espero esto para ayudar a otras personas con necesidades más específicas.

+1

Los ObjectURL son por definición locales. Las URL de objeto son URL que apuntan a archivos en el disco. Dado que no existe un objectURL entre dominios, está combinando dos conceptos diferentes, por lo tanto, su problema al usar la solución dada. – BrianFreud

+1

@BrianFreud Entiendo que esa no es exactamente la respuesta a esta pregunta. Pero todavía creo que es una buena respuesta para irme ya que llegué aquí buscando la respuesta a una pequeña pregunta diferente '¿Cómo obtener un archivo o blob de una URL?'. Si marca su propia respuesta, hay 10 votos positivos en 'No funciona en caso de solicitudes de dominios cruzados. '. Así que más de 10 personas llegaron aquí buscando eso. Decidí entonces dejarlo aquí. –

+0

El problema es que su respuesta a sabiendas no responde a esta pregunta. Una URL normal y una URL de objeto son dos cosas completamente diferentes. En cuanto al número de votos positivos en "No funciona en caso de solicitudes de dominios cruzados", ¿no crees que sería mejor explicar por qué es literalmente imposible aquí, y señalar a algún lugar que muestre la respuesta para las URL normales, en lugar de que confundir las cosas aquí al combinar URL normales y URLs objeto? – BrianFreud

1

Quizás alguien encuentre esto útil cuando se trabaja con React/Node/Axios. Utilicé esto para mi función de carga de imágenes Cloudinary con react-dropzone en la interfaz de usuario.

axios({ 
     method: 'get', 
     url: file[0].preview, // blob url eg. blob:http://127.0.0.1:8000/e89c5d87-a634-4540-974c-30dc476825cc 
     responseType: 'blob' 
    }).then(function(response){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(response.data); 
     reader.onloadend = function() { 
      var base64data = reader.result; 
      self.props.onMainImageDrop(base64data) 
     } 

    }) 
Cuestiones relacionadas