2012-08-09 3 views
76

Sto permettendo all'utente di caricare immagini in una pagina tramite trascinamento & e altri metodi. Quando un'immagine viene eliminata, sto usando URL.createObjectURL per convertire in un URL oggetto per visualizzare l'immagine. Non sto revocando l'url, perché lo riuso.Come ottenere un file o un blob dall'URL di un oggetto?

Così, quando arriva il momento di creare un oggetto FormData in modo da poter permettere loro di caricare un modulo con una di quelle immagini in esso, c'è qualche modo per poi invertire tale URL oggetto di nuovo in un Blob o File così Posso quindi aggiungerlo a un oggetto FormData?

+0

non importa sui due precedenti commenti: tutto ciò che devi fare è inviare un 'XMLHttpRequest' all'URL del blob. – gengkev

+7

che bella domanda! –

+0

Perché non memorizzare semplicemente gli oggetti del file originale da qualche parte, quindi utilizzare l'URL dell'oggetto per visualizzarli e sul modulo di invio utilizzare i file originali? – user764754

risposta

52

Come gengkev allude nel suo commento di cui sopra, sembra che il migliore/unico modo per farlo è con una chiamata asincrona 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

Non funziona in caso di richieste tra domini diversi. –

+14

Quando avresti mai un * objectURL * che non è locale per il dominio e l'ambito corrente? – BrianFreud

+4

ho fatto lo stesso come sopra, ma ho ottenuto 404 non trovato con il xhr. cosa sta succedendo? –

2

Se si mostra il file in una tela in ogni caso è anche possibile convertire il contenuto del canvas in un oggetto 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

Nota che in realtà non ti restituisce lo * stesso * file originale; sta creando un nuovo file immagine al volo. Quando l'ho testato per l'ultima volta un paio di anni fa, ho scoperto che almeno in Chrome, il nuovo file immagine non è affatto compresso: avevo 10k jpg trasformati in jpg da 2.5 mb. – BrianFreud

0

Purtroppo @ risposta di BrianFreud non si adatta alle mie esigenze, ho avuto un po 'diversa esigenza e so che non è la risposta alla domanda di @ BrianFreud, ma la lascio qui perché molte persone sono arrivate qui con la mia stessa necessità. Avevo bisogno di qualcosa come "Come ottenere un file o un blob da un URL?", E la risposta corretta attuale non si adatta alle mie esigenze perché non è un dominio incrociato.

Ho un sito web che consuma le immagini da un Amazon S3/Azure, e lì ho memorizzare oggetti con nome con uniqueidentifiers:

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

Alcune di queste immagini devono essere scaricate dalla nostra interfaccia di sistema. Per evitare di passare questo traffico attraverso il mio server HTTP, poiché questo oggetto non richiede l'accesso a nessuna sicurezza (eccetto il filtro del dominio), ho deciso di fare una richiesta diretta sul browser dell'utente e utilizzare l'elaborazione locale per dare al file un vero nome ed estensione.

per realizzare che ho usato questo grande articolo da Henry Algus: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1. Primo passo: Aggiungere il supporto binario a 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. Secondo passo: Fai un richiesta utilizzando questo tipo di trasporto.

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

Ora è possibile utilizzare il Blob creato come si vuole, nel mio caso voglio salvarlo su disco.

3. Opzionale: Salva file sul computer dell'utente utilizzando FileSaver

ho usato FileSaver.js per salvare su disco il file scaricato, se è necessario per realizzare questo, si prega di utilizzare questa libreria javascript:

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

mi aspetto questo per aiutare gli altri con esigenze più specifiche.

+1

Gli ObjectURL sono per definizione locali. Gli URL oggetto sono URL che puntano a file su disco. Dato che non esiste nulla come objectURL tra domini, stai combinando due concetti diversi, quindi il tuo problema usando la soluzione data. – BrianFreud

+1

@BrianFreud Ho capito che non è esattamente la risposta a questa domanda. Ma continuo a pensare che sia una buona risposta a partire da quando sono arrivato qui cercando la risposta a una domanda leggermente diversa "Come ottenere un file o un blob da un URL?". Se controlli la tua risposta, ci sono 10 upvotes su "Non funziona in caso di richieste cross domain. '. Quindi più di 10 persone sono arrivate qui a cercarlo. Ho deciso di lasciarlo qui. –

+0

Il problema è che la tua risposta consapevolmente non risponde a questa domanda. Un normale URL e un oggetto URL sono due cose completamente diverse. Per quanto riguarda il numero di voti positivi su "Non funziona in caso di richieste interdominio", non penseresti che sarebbe meglio spiegare perché è letteralmente impossibile qui, e puntare a un punto che mostri la risposta per gli URL normali, piuttosto che confondere le cose qui confondendo gli URL normali e gli URL degli oggetti? – BrianFreud

1

Forse qualcuno lo trova utile quando si lavora con React/Node/Axios. Ho usato questo per la mia funzione di upload di immagini Cloudinary con react-dropzone nell'interfaccia utente.

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

    }) 
Problemi correlati