O que é um URL de blob e por que é usado?

348

Estou tendo muitos problemas com o URL de blob.

Eu estava procurando por srcuma tag de vídeo no YouTube e achei que o vídeo srcera como:

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

Abri o URL do blob que estava no srcvídeo e deu um erro. Não consigo abrir o link, mas ele estava funcionando com a srctag. Como isso é possível?

Requisitos:

  • O que é URL de blob?
  • Por que é usado?
  • Posso criar meu próprio URL de blob em um servidor?
  • Se você tiver detalhes adicionais
Waqas Tahir
fonte
3
Essencialmente, não permite hotlinking. (like youtube)
facepalm42

Respostas:

349

URLs de blob (ref W3C , nome oficial) ou URLs de objeto (ref. MDN e nome do método) são usados ​​com um objeto Blob ou File .

src = "blob: https: //crap.crap " Abri o URL do blob que estava no src do vídeo, deu um erro e não consigo abrir, mas estava trabalhando com a tag src como é possível?

URLs de blob só podem ser gerados internamente pelo navegador. URL.createObjectURL()criará uma referência especial ao objeto Blob ou File, que poderá ser liberado posteriormente usando URL.revokeObjectURL(). Esses URLs podem ser usados ​​apenas localmente na instância única do navegador e na mesma sessão (ou seja, a vida da página / documento).

O que é um URL de blob?
Por que é usado?

URL de blob / URL de objeto é um pseudo-protocolo para permitir que os objetos Blob e File sejam usados ​​como fonte de URL para coisas como imagens, links de download para dados binários e assim por diante.

Por exemplo, você não pode entregar dados de bytes brutos de um objeto Image, pois ele não saberia o que fazer com ele. Requer, por exemplo, imagens (que são dados binários) para serem carregadas via URLs. Isso se aplica a qualquer coisa que exija um URL como fonte. Em vez de fazer o upload dos dados binários, em seguida, servi-os novamente por meio de uma URL, é melhor usar uma etapa local extra para poder acessar os dados diretamente sem precisar acessar um servidor.

Também é uma alternativa melhor ao Data-URI, que são cadeias codificadas como Base-64 . O problema com o Data-URI é que cada caracter ocupa dois bytes em JavaScript. Além disso, 33% são adicionados devido à codificação Base-64. Os blobs são arrays de bytes binários puros que não possuem sobrecarga significativa como o Data-URI, o que os torna mais rápidos e menores de manipular.

Posso criar meu próprio URL de blob em um servidor?

Não, URLs de blob / URLs de objetos podem ser criados apenas internamente no navegador. Você pode criar Blobs e obter o objeto File através da API do File Reader, embora BLOB signifique OBject grande binário e seja armazenado como matriz de bytes. Um cliente pode solicitar que os dados sejam enviados como ArrayBuffer ou Blob. O servidor deve enviar os dados como dados binários puros. Os bancos de dados geralmente usam o Blob para descrever objetos binários e, em essência, estamos falando basicamente de matrizes de bytes.

se você tiver detalhes adicionais

Você precisa encapsular os dados binários como um objeto BLOB e, em seguida, usar URL.createObjectURL()para gerar uma URL local para ele:

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

Observe que URLpode ser prefixado em navegadores da webkit, então use:

var url = (URL || webkitURL).createObjectURL(...);
Bakudan
fonte
19
Nas últimas 6 horas, tenho tentado fazer com que o PHP transforme um URL de objeto passado do AJAX em um arquivo de imagem. Somente depois de ler sua explicação, percebi por que não estava gravando nenhum dado no arquivo. Sua explicação concisa e completa pôs fim à minha miséria. Obrigado.
Partack
4
@ K3N é possível obter a verdadeira fonte do URL do blob em vez do URL gerado? Nest cam gera um URL blob para impedir as pessoas de gravação de suas próprias câmeras
Alex Kwitny
4
iluminação para mim "BLOB apenas significa grande objeto binário"
canbax
6
É possível recuperar o conteúdo do objeto blob / arquivo e baixar o que quer que seja (imagem ou vídeo)?
DFSFOT 17/01/19
4
Isso pode ser pertinente para as pessoas querendo saber como baixar um vídeo blob: stackoverflow.com/q/42901942/1530508
ApproachingDarknessFish
10

Esta função Javascript pretende mostrar a diferença entre a API de arquivos Blob e a API de dados para baixar um arquivo JSON no navegador do cliente:

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

A função é chamada como saveAsFile('out.json', jsonString);. Ele criará um ByteStream imediatamente reconhecido pelo navegador que fará o download do arquivo gerado diretamente usando a API de arquivos URL.createObjectURL.

No else, é possível ver o mesmo resultado obtido através do hrefelemento mais a API de dados, mas isso tem várias limitações que a API de Blob não possui.

Loretoparisi
fonte
11
Você pode adaptar isso para salvar um vídeo de um tweet?
logicbloke
3

O que é um URL de blob? Por que é usado?

BLOB é apenas uma sequência de bytes. O navegador reconhece como fluxo de bytes. É usado para obter fluxo de bytes da fonte.

Um objeto Blob representa um objeto semelhante a um arquivo de dados brutos imutáveis. Os blobs representam dados que não estão necessariamente em um formato nativo de JavaScript. A interface do arquivo é baseada no Blob, herdando a funcionalidade do blob e expandindo-a para oferecer suporte a arquivos no sistema do usuário.

Posso criar meu próprio URL de blob em um servidor?

Sim, é possível que haja maneiras servidoras de fazer isso, por exemplo, tente http://php.net/manual/en/function.ibase-blob-echo.php

Leia mais sobre

Robert
fonte
2
Posso obter algum benefício usando o URL BLOB?
Waqas Tahir
Você pode ler isso para obter sua resposta. Obviamente, existem prós e contras.
Robert
4
Você está misturando URLs de objeto com BLOBs. O URL do objeto é um pseudo-protocolo para permitir que BLOBs sejam usados ​​como fonte de URI.
4
Existem algumas falhas significativas nessa resposta. Principalmente como apontado em um comentário anterior, alguns conceitos muito diferentes são misturados ... e depois compactados em uma resposta incompleta e incorreta.
trs 25/03
2

Eu modifiquei a solução de trabalho para lidar com os dois casos ... quando o vídeo é carregado e quando a imagem é carregada .. espero que ajude alguns.

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/

Pratap Dessai
fonte
1. Qual é o propósito do recuo no seu código? Todo mundo usa recuo para destacar a estrutura lógica do código. 2. Seu JSFiddle não faz nada. Eu tentei fazer upload de uma imagem e um vídeo.
7vujy0f0hy