2012-08-09 5 views
76

Ich erlaube dem Benutzer, Bilder in eine Seite per Drag & Drop und andere Methoden zu laden. Wenn ein Bild gelöscht wird, verwende ich URL.createObjectURL, um es in eine Objekt-URL zu konvertieren, um das Bild anzuzeigen. Ich widerrufe die URL nicht, da ich sie wiederverwende.Wie bekomme ich eine Datei oder ein Blob von einer Objekt-URL?

Also, wenn es darum geht, ein FormData Objekt zu erstellen, so erlaube ich kann ihnen eine Form mit einem dieser Bilder darin zu laden, gibt es einige, wie ich dann, dass Objekt-URL in eine Blob oder File so umkehren Ich kann es dann an ein FormData Objekt anhängen?

+0

Vergesst die letzten beiden Kommentare nicht - alles, was Sie tun müssen, ist ein 'XMLHttpRequest' an die Blob-URL zu senden. – gengkev

+7

was für eine tolle Frage! –

+0

Warum speichern Sie nicht einfach die ursprünglichen Dateiobjekte irgendwo, verwenden Sie dann die Objekt-URL, um sie anzuzeigen, und verwenden Sie beim Senden des Formulars die Originaldateien? – user764754

Antwort

52

Wie gengkev oben in seinem Kommentar anspielt, es sieht aus wie die beste/einzige Weg, dies mit einem Asynchron xhr2 Aufruf ist zu tun:

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

Es funktioniert nicht bei domänenübergreifenden Anfragen. –

+14

Wann würden Sie jemals eine * objectURL * haben, die für die aktuelle Domäne und den aktuellen Bereich nicht lokal ist? – BrianFreud

+4

ich tat es gleich wie oben, aber 404 mit der Xhr nicht gefunden. Was ist los? –

2

Wenn Sie die Datei in einer Leinwand sowieso zeigen können Sie auch Konvertieren Sie den Canvas-Inhalt in ein Blob-Objekt.

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

Beachten Sie, dass Sie damit nicht die * gleiche * Originaldatei erhalten; es erstellt eine neue Bilddatei im laufenden Betrieb. Als ich das vor ein paar Jahren zum letzten Mal getestet habe, habe ich zumindest in Chrome festgestellt, dass die neue Bilddatei überhaupt nicht komprimiert ist - ich habe aus 10k JPGs 2,5 MB jpgs gemacht. – BrianFreud

3

Getting BLOB data from XHR request Sie, welche darauf hinweist, dass BlobBuilder nicht in Chrome funktioniert, so dass Sie verwenden müssen:

xhr.responseType = 'arraybuffer'; 
0

Leider @ Antwort BrianFreud ist nicht meine Bedürfnisse passen, hatte ich ein wenig anders Notwendigkeit und ich weiß, dass das nicht die Antwort auf @ BrianFreuds Frage ist, aber ich verlasse es hier, weil viele Leute mit meinem gleichen Bedürfnis hergekommen sind. Ich brauchte etwas wie "Wie bekomme ich eine Datei oder einen Blob von einer URL?", Und die aktuell richtige Antwort passt nicht zu meinen Bedürfnissen, da sie nicht domänenübergreifend ist.

Ich habe eine Website, die Bilder von einem Amazon S3/Azure Storage verbraucht, und es speichere ich Objekte mit uniqueidentifiers genannt:

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

Einige dieser Bilder sollten von unserer Systemschnittstelle heruntergeladen werden. Um zu vermeiden, dass dieser Datenverkehr über meinen HTTP-Server geleitet wird, da auf diese Objekte kein Zugriff erforderlich ist (außer durch Domänenfilterung), habe ich eine direkte Anfrage an den Browser des Benutzers gestellt und die lokale Verarbeitung verwendet, um der Datei einen echten Namen zu geben und Erweiterung.

Um das zu erreichen, dass ich diesen großen Artikel von Henry Algus verwendet haben: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1. Erster Schritt : Binärunterstützung In den 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. Zweiter Schritt: a Stellen Anfrage mit diesem Transporttyp.

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

Jetzt können Sie das Blob erstellt verwenden, wie Sie wollen, in meinem Fall habe ich es auf der Festplatte gespeichert werden soll.

3. Optional: Speichern Sie die Datei auf dem Computer des Benutzers FileSaver- mit

I FileSaver- verwendet haben.js auf der Festplatte die heruntergeladene Datei zu speichern, wenn Sie das erreichen müssen, verwenden Sie bitte diese Javascript-Bibliothek:

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

Ich erwarte, dass diese andere mit mehr spezifischen Bedürfnissen zu helfen.

+1

ObjectURLs sind per Definition lokal. Objekt-URLs sind URLs, die auf Dateien auf dem Datenträger verweisen. Da es kein domänenübergreifendes ObjektURL gibt, durchkämmen Sie zwei verschiedene Konzepte, also Ihr Problem mit der gegebenen Lösung. – BrianFreud

+1

@BrianFreud Ich habe es, das ist nicht genau die Antwort auf diese Frage. Aber ich denke immer noch, dass es eine gute Antwort ist zu gehen, seit ich hier bin, um nach der Antwort auf eine etwas andere Frage zu suchen: "Wie bekomme ich eine Datei oder einen Blob von einer URL?". Wenn Sie Ihre eigene Antwort überprüfen, gibt es 10 Upvotes zu 'Es funktioniert nicht bei domänenübergreifenden Anfragen. ". Also haben mehr als 10 Personen hier gesucht. Ich beschloss, es hier zu lassen. –

+0

Problem ist, Ihre Antwort beantwortet diese Frage wissentlich nicht. Eine normale URL und eine Objekt-URL sind zwei völlig verschiedene Dinge. In Bezug auf die Anzahl der Upvotes zu "Es funktioniert nicht im Fall von domainübergreifenden Anfragen.", Würden Sie nicht besser erklären, warum das hier wirklich unmöglich ist, und auf etwas verweisen, das eher die Antwort für normale URLs zeigt als verwirren Dinge hier durch Zusammenführen von normalen URLs und Objekt-URLs? – BrianFreud

1

Vielleicht findet jemand das nützlich, wenn er mit React/Node/Axios arbeitet. Ich habe dies für meine Cloudinary-Bild-Upload-Funktion mit react-dropzone auf der Benutzeroberfläche verwendet.

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

    }) 
Verwandte Themen