Co to jest adres URL obiektu blob i dlaczego jest używany?


349

Mam wiele problemów z adresem URL obiektu blob.

Szukałem srctagu wideo na YouTube i odkryłem, że film srcbył podobny do:

src="blob:https://crap.crap"

Otworzyłem adres URL obiektu blob, który był w srcfilmie, w którym wystąpił błąd. Nie mogę otworzyć linku, ale działał z srctagiem. Jak to jest możliwe?

Wymagania:

  • Co to jest adres URL obiektu blob?
  • Dlaczego jest używany?
  • Czy mogę utworzyć własny adres URL obiektu blob na serwerze?
  • Jeśli masz dodatkowe informacje


3
Zasadniczo nie zezwala na hotlinkowanie. (jak youtube)
facepalm42

Odpowiedzi:


349

Adresy URL obiektów blob (ref. W3C , oficjalna nazwa) lub URL-e obiektów (ref. MDN i nazwa metody) są używane z obiektem Blob lub File .

src = "blob: https: //crap.crap " Otworzyłem adres URL blob, który był w src wideo, dał błąd i nie mogę go otworzyć, ale działałem z tagiem src, jak to możliwe?

Adresy URL obiektów blob mogą być generowane tylko wewnętrznie przez przeglądarkę. URL.createObjectURL()utworzy specjalne odwołanie do obiektu Blob lub File, który później można zwolnić za pomocą URL.revokeObjectURL(). Te adresy URL mogą być używane lokalnie tylko w jednym wystąpieniu przeglądarki i w tej samej sesji (tj. W czasie życia strony / dokumentu).

Co to jest adres URL obiektu blob?
Dlaczego jest używany?

Adres URL obiektu Blob / URL obiektu to pseudo protokół, który umożliwia stosowanie obiektów obiektów Blob i plików jako źródła adresu URL dla takich rzeczy, jak obrazy, łącza pobierania danych binarnych i tak dalej.

Na przykład nie można przekazać surowego bajtu danych obiektowi Image, ponieważ nie wiedziałby, co z nim zrobić. Wymaga na przykład ładowania obrazów (które są danymi binarnymi) za pośrednictwem adresów URL. Dotyczy to wszystkiego, co wymaga adresu URL jako źródła. Zamiast przesyłać dane binarne, a następnie podawać je z powrotem za pomocą adresu URL, lepiej skorzystać z dodatkowego lokalnego kroku, aby uzyskać dostęp do danych bezpośrednio, bez konieczności przechodzenia przez serwer.

Jest to także lepsza alternatywa dla Data-URI, które są łańcuchami kodowanymi jako Base-64 . Problem z Data-URI polega na tym, że każdy znak zajmuje dwa bajty w JavaScript. Ponadto 33% jest dodawane ze względu na kodowanie Base-64. Obiekty BLOB są czystymi binarnymi tablicami bajtowymi, które nie mają znaczącego obciążenia, podobnie jak identyfikator URI danych, co czyni je szybszymi i mniejszymi w obsłudze.

Czy mogę utworzyć własny adres URL obiektu blob na serwerze?

Nie, adresy URL obiektów Blob / URL obiektów można tworzyć tylko wewnętrznie w przeglądarce. Możesz tworzyć obiekty BLOB i pobierać obiekt File za pomocą interfejsu API czytnika plików, chociaż BLOB oznacza po prostu duży obiekt binarny i jest przechowywany jako tablice bajtów. Klient może zażądać przesłania danych jako ArrayBuffer lub jako obiekt Blob. Serwer powinien wysłać dane jako czyste dane binarne. Bazy danych często używają obiektu Blob również do opisywania obiektów binarnych, i zasadniczo mówimy w zasadzie o tablicach bajtowych.

jeśli masz, to dodatkowe szczegóły

Musisz obudować dane binarne jako obiekt BLOB, a następnie użyć URL.createObjectURL()do wygenerowania lokalnego adresu URL:

var blob = new Blob([arrayBufferWithPNG], {type: "image/png"}),
    url = URL.createObjectURL(blob),
    img = new Image();

img.onload = function() {
    URL.revokeObjectURL(this.src);     // clean-up memory
    document.body.appendChild(this);   // add image to DOM
}

img.src = url;                         // can now "stream" the bytes

Pamiętaj, że URLmoże być prefiksem w przeglądarkach internetowych, więc użyj:

var url = (URL || webkitURL).createObjectURL(...);

19
Przez ostatnie 6 godzin próbowałem zmusić PHP do przekształcenia adresu URL obiektu przekazanego z AJAX do pliku obrazu. Dopiero po przeczytaniu twojego wyjaśnienia zrozumiałem, dlaczego nie zapisuje żadnych danych w pliku. Twoje zwięzłe i dokładne wyjaśnienie położyło kres mojej nędzy. Dziękuję Ci.
Partack

4
@ K3N czy możliwe jest uzyskanie prawdziwego źródła adresu URL obiektu blob zamiast wygenerowanego adresu URL? Nest cam generuje adres URL obiektu blob, aby uniemożliwić ludziom nagrywanie własnych kamer
Alex Kwitny,

4
oświecenie dla mnie „BLOB oznacza po prostu duży obiekt binarny”
canbax

6
Czy można pobrać zawartość obiektu blob / pliku i pobrać cokolwiek to jest (obraz lub wideo)?
DFSFOT

4
Może to dotyczyć osób zastanawiających się, jak pobrać wideo typu blob: stackoverflow.com/q/42901942/1530508
ApproachingDarknessFish

10

Ta funkcja Javascript ma na celu pokazać różnicę między interfejsem API pliku Blob a interfejsem API Data w celu pobrania pliku JSON w przeglądarce klienta:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @author Loreto Parisi
 */

var saveAsFile = function(fileName, fileContents) {
    if (typeof(Blob) != 'undefined') { // Alternative 1: using Blob
        var textFileAsBlob = new Blob([fileContents], {type: 'text/plain'});
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        } else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else { // Alternative 2: using Data
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' +
            encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
} // saveAsFile

/* Example */
var jsonObject = {"name": "John", "age": 30, "car": null};
saveAsFile('out.json', JSON.stringify(jsonObject, null, 2));

Funkcja nazywa się jak saveAsFile('out.json', jsonString);. Stworzy ByteStream natychmiast rozpoznany przez przeglądarkę, która pobierze wygenerowany plik bezpośrednio za pomocą interfejsu API File URL.createObjectURL.

W polu elsemożna zobaczyć ten sam wynik uzyskany przez hrefelement plus Data API, ale ma to kilka ograniczeń, których nie ma interfejs Blob API.


1
Czy możesz to dostosować, aby zapisać film z tweeta?
logicbloke

3

Co to jest adres URL obiektu blob? Dlaczego jest używany?

BLOB jest sekwencją bajtów. Przeglądarka rozpoznaje go jako strumień bajtów. Służy do pobierania strumienia bajtów ze źródła.

Obiekt Blob reprezentuje podobny do pliku obiekt niezmiennych, surowych danych. Obiekty BLOB reprezentują dane, które niekoniecznie są w formacie natywnym JavaScript. Interfejs pliku jest oparty na obiekcie Blob, dziedziczącym funkcjonalność obiektów blob i rozszerzającym go o obsługę plików w systemie użytkownika.

Czy mogę utworzyć własny adres URL obiektu blob na serwerze?

Tak, możesz to zrobić na wiele sposobów, na przykład spróbuj http://php.net/manual/en/function.ibase-blob-echo.php

Czytaj więcej na


2
Czy mogę uzyskać jakąkolwiek korzyść, korzystając z adresu URL BLOB?
Waqas Tahir

Można odczytać to , aby uzyskać odpowiedź. Oczywiście są plusy i minusy.
Robert

4
Mieszasz adresy URL obiektów z BLOBami. Object-URL to pseudo protokół, który pozwala na użycie BLOB-ów jako źródła URI.

4
Istnieje kilka istotnych wad tej odpowiedzi. Głównie, jak wskazano w poprzednim komentarzu, niektóre bardzo różne koncepcje mieszają się ... a następnie są kompresowane w niekompletną i niepoprawną odpowiedź.
trs

2

Zmodyfikowałem działające rozwiązanie, aby poradzić sobie zarówno z tym przypadkiem .. gdy przesyłany jest film, jak i gdy przesyłany jest obraz .. mam nadzieję, że to pomoże.

HTML

<input type="file" id="fileInput">
<div> duration: <span id='sp'></span><div>

JavaScript

var fileEl = document.querySelector("input");

fileEl.onchange = function(e) {


    var file = e.target.files[0]; // selected file

    if (!file) {
        console.log("nothing here");
        return;
    }

    console.log(file);
    console.log('file.size-' + file.size);
    console.log('file.type-' + file.type);
    console.log('file.acutalName-' + file.name);

    let start = performance.now();

    var mime = file.type, // store mime for later
        rd = new FileReader(); // create a FileReader

    if (/video/.test(mime)) {

        rd.onload = function(e) { // when file has read:


            var blob = new Blob([e.target.result], {
                    type: mime
                }), // create a blob of buffer
                url = (URL || webkitURL).createObjectURL(blob), // create o-URL of blob
                video = document.createElement("video"); // create video element
            //console.log(blob);
            video.preload = "metadata"; // preload setting

            video.addEventListener("loadedmetadata", function() { // when enough data loads
                console.log('video.duration-' + video.duration);
                console.log('video.videoHeight-' + video.videoHeight);
                console.log('video.videoWidth-' + video.videoWidth);
                //document.querySelector("div")
                //  .innerHTML = "Duration: " + video.duration + "s" + " <br>Height: " + video.videoHeight; // show duration
                (URL || webkitURL).revokeObjectURL(url); // clean up

                console.log(start - performance.now());
                // ... continue from here ...

            });
            video.src = url; // start video load
        };
    } else if (/image/.test(mime)) {
        rd.onload = function(e) {

            var blob = new Blob([e.target.result], {
                    type: mime
                }),
                url = URL.createObjectURL(blob),
                img = new Image();

            img.onload = function() {
                console.log('iamge');
                console.dir('this.height-' + this.height);
                console.dir('this.width-' + this.width);
                URL.revokeObjectURL(this.src); // clean-up memory
                console.log(start - performance.now()); // add image to DOM
            }

            img.src = url;

        };
    }

    var chunk = file.slice(0, 1024 * 1024 * 10); // .5MB
    rd.readAsArrayBuffer(chunk); // read file object

};

jsFiddle Url

https://jsfiddle.net/PratapDessai/0sp3b159/


1. Jaki jest cel wcięcia w twoim kodzie? Wszyscy inni używają wcięć do podkreślenia logicznej struktury kodu. 2. Twój JSFiddle nic nie robi. Próbowałem załadować obraz i film.
7vujy0f0hy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.