Blob dari DataURL?

92

Menggunakan FileReaderIni readAsDataURL()saya dapat mengubah data sewenang-wenang menjadi URL Data. Apakah ada cara untuk mengubah URL Data kembali menjadi sebuah Blobinstance menggunakan apis browser bawaan?

Shane Holloway
sumber

Jawaban:

151

Pengguna Matt telah mengusulkan kode berikut setahun yang lalu ( Bagaimana cara mengonversi dataURL ke objek file dalam javascript? ) Yang dapat membantu Anda

EDIT: Seperti yang dilaporkan beberapa komentator, BlobBuilder sudah tidak digunakan lagi beberapa waktu lalu. Ini adalah kode yang diperbarui:

function dataURItoBlob(dataURI) {
  // convert base64 to raw binary data held in a string
  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
  var byteString = atob(dataURI.split(',')[1]);

  // separate out the mime component
  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

  // write the bytes of the string to an ArrayBuffer
  var ab = new ArrayBuffer(byteString.length);

  // create a view into the buffer
  var ia = new Uint8Array(ab);

  // set the bytes of the buffer to the correct values
  for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
  }

  // write the ArrayBuffer to a blob, and you're done
  var blob = new Blob([ab], {type: mimeString});
  return blob;

}
devnull69
sumber
4
Perpecahan duplikat tampaknya sedikit boros, mengingat ini bisa menjadi string yang sangat besar.
Jesse Crossen
2
Apa peran dari variabel "ia" - nilainya diberikan tetapi tidak pernah digunakan dalam membentuk blob. Mengapa?
Nyalakan
1
Blaze, Ward: ia adalah view dari buffer. Jadi ketika Anda mengatur setiap byte di ia, itu menulis ke buffer. Tanpa loop over ia buffer akan benar-benar kosong.
Mat
1
Bagaimana cara menemukan jawaban SO # 6850276?
BT
1
@BT: Saya kira stackoverflow.com/a/30407840/271577 dimaksudkan (perhatikan URL yang diarahkan ulang menyertakan "# 6850276").
Brett Zamir
50

Suka metode @Adria tetapi dengan Fetch api dan [ caniuse? ]
Tidak perlu memikirkan mimetype karena jenis respons blob langsung bekerja di luar kotak

Peringatan: Dapat melanggar Content Security Policy (CSP)
... jika Anda menggunakan barang itu

var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="

fetch(url)
.then(res => res.blob())
.then(blob => console.log(blob))

Jangan berpikir Anda bisa melakukannya lebih kecil dari ini tanpa menggunakan lib's

Tak ada habisnya
sumber
1
Sangat elegan. Sayangnya edge 13 dan safari tidak mendukung "fetch".
alex_1948511
2
Ini didukung di edge 14 dan safari 10.1
Endless
19
Versi asinkron:const blob = await (await fetch(url)).blob();
Christian d'Heureuse
Berfungsi dengan baik, tetapi file tidak memiliki ekstensi saat dibaca dari server. Ada pemikiran?
pauljeba
1
Masalah yang lebih besar dari ini fetchadalah memaksa untuk memiliki API asinkron.
Dennis C
19
dataURItoBlob : function(dataURI, dataTYPE) {
        var binary = atob(dataURI.split(',')[1]), array = [];
        for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i));
        return new Blob([new Uint8Array(array)], {type: dataTYPE});
    }

input dataURI adalah Data URL dan dataTYPE adalah jenis file dan kemudian objek blob output

Shawn Wu
sumber
1
Itu dataTYPEtertanam dataURIdan karenanya harus diuraikan seperti pada jawaban pertama.
Noel Abrahams
dataURL2Blob berasal dari plugin saya untuk proses gambar, Anda dapat melihat tautan ini. Saya hanya menyalin kode saya sendiri. github.com/xenophon566/html5.upload/blob/master/js/…
Shawn Wu
12

Metode berbasis XHR.

function dataURLtoBlob( dataUrl, callback )
{
    var req = new XMLHttpRequest;

    req.open( 'GET', dataUrl );
    req.responseType = 'arraybuffer'; // Can't use blob directly because of https://crbug.com/412752

    req.onload = function fileLoaded(e)
    {
        // If you require the blob to have correct mime type
        var mime = this.getResponseHeader('content-type');

        callback( new Blob([this.response], {type:mime}) );
    };

    req.send();
}

dataURLtoBlob( 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', function( blob )
{
    console.log( blob );
});
Adria
sumber
Sepertinya, ini cara terbaik sekarang. Terima kasih!
dizel3d
Tidak akan berfungsi di Safari - ini akan memunculkan kesalahan lintas sumber jika halaman dimuat dari HTTPS.
Martin Ždila
Pertanyaannya adalah Blob dari DataURL?
Michal
7

Di peramban modern, seseorang dapat menggunakan satu baris yang disarankan oleh Christian d'Heureuse dalam komentar:

const blob = await (await fetch(dataURI)).blob(); 
Jan Derk
sumber
3

mencoba:

function dataURItoBlob(dataURI) {
    if(typeof dataURI !== 'string'){
        throw new Error('Invalid argument: dataURI must be a string');
    }
    dataURI = dataURI.split(',');
    var type = dataURI[0].split(':')[1].split(';')[0],
        byteString = atob(dataURI[1]),
        byteStringLength = byteString.length,
        arrayBuffer = new ArrayBuffer(byteStringLength),
        intArray = new Uint8Array(arrayBuffer);
    for (var i = 0; i < byteStringLength; i++) {
        intArray[i] = byteString.charCodeAt(i);
    }
    return new Blob([intArray], {
        type: type
    });
}
HaNdTriX
sumber
2

Buat blob menggunakan XHR API :

function dataURLtoBlob( dataUrl, callback )
{
    var req = new XMLHttpRequest;

    req.open( 'GET', dataUrl );
    req.responseType = 'blob';

    req.onload = function fileLoaded(e)
    {
        callback(this.response);
    };

    req.send();
}

var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='

dataURLtoBlob(dataURI , function( blob )
{
    console.log( blob );
});

georgeawg.dll
sumber
0

Gunakan kode saya, ubah dataURI ke blob. Ini lebih sederhana dan lebih bersih dari yang lain.

function dataURItoBlob(dataURI) {
    var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1];
    return new Blob([atob(arr[1])], {type:mime});
}
cuixiping
sumber
Bisakah Anda menjelaskan mengapa kode Anda tidak memerlukan konversi ke int array sementara orang lain melakukannya?
Ameen
Lihat konstruktor Blob () di MDN
cuixiping
@Rikard apa maksudmu? itu tidak mempengaruhi gambar apapun
cuixiping
2
Ini hanya berfungsi untuk beberapa hal dasar. Anda harus keluar dari + decodeURIComponent terlebih dahulu untuk mendukung sebagian besar pengkodean konten, baca ini . Itulah mengapa orang lain mengonversi string menjadi larik int untuk menghindari panggilan fungsi decodeURIComponent / atob lambat / lapar dan mengonversi langsung ke byte
Endless
0

Karena tidak satu pun dari jawaban ini yang mendukung dataURL base64 dan non-base64, berikut adalah salah satu yang mendukung jawaban vuamitom yang dihapus:

// from /programming/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/
var dataURLtoBlob = exports.dataURLtoBlob = function(dataurl) {
    var parts = dataurl.split(','), mime = parts[0].match(/:(.*?);/)[1]
    if(parts[0].indexOf('base64') !== -1) {
        var bstr = atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n)
        while(n--){
            u8arr[n] = bstr.charCodeAt(n)
        }

        return new Blob([u8arr], {type:mime})
    } else {
        var raw = decodeURIComponent(parts[1])
        return new Blob([raw], {type: mime})
    }
}

Catatan: Saya tidak yakin apakah ada jenis mime dataURL lain yang mungkin harus ditangani secara berbeda. Tapi tolong beri tahu saya jika Anda mengetahuinya! Mungkin saja dataURL dapat memiliki format apa pun yang diinginkan, dan dalam hal ini terserah Anda untuk menemukan kode yang tepat untuk kasus penggunaan khusus Anda.

BT
sumber
-2

menggunakan

FileReader.readAsArrayBuffer(Blob|File)

daripada

FileReader.readAsDataURL(Blob|File)
3on
sumber
2
Saya harus menyimpannya sebagai DataURL untuk waktu yang tidak terbatas di localStorage, jadi menggunakan ArrayBufferjalur alternatif tidak akan berfungsi.
Shane Holloway