The atob
fungsi akan memecahkan kode string Base64 menjadi string baru dengan karakter untuk setiap byte dari data biner.
const byteCharacters = atob(b64Data);
Setiap titik kode karakter (charCode) akan menjadi nilai byte. Kita bisa membuat array nilai byte dengan menerapkan ini menggunakan .charCodeAt
metode untuk setiap karakter dalam string.
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
Anda dapat mengubah array nilai byte ini menjadi array byte yang diketik nyata dengan meneruskannya ke Uint8Array
konstruktor.
const byteArray = new Uint8Array(byteNumbers);
Ini pada gilirannya dapat dikonversi ke BLOB dengan membungkusnya dalam sebuah array dan meneruskannya ke Blob
konstruktor.
const blob = new Blob([byteArray], {type: contentType});
Kode di atas berfungsi. Namun kinerjanya dapat ditingkatkan sedikit dengan memproses byteCharacters
irisan yang lebih kecil, daripada sekaligus. Dalam pengujian kasar saya 512 byte tampaknya merupakan ukuran irisan yang baik. Ini memberi kita fungsi berikut.
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
window.location = blobUrl;
Contoh Lengkap:
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
Berikut adalah metode yang lebih minimal tanpa dependensi atau pustaka.
Itu membutuhkan API ambil yang baru. ( Bisakah saya menggunakannya? )
Dengan metode ini Anda juga dapat dengan mudah mendapatkan ReadableStream, ArrayBuffer, teks, dan JSON.
Sebagai fungsi:
Saya melakukan tes kinerja sederhana terhadap versi sinkronisasi ES6 Jeremy.
Versi sinkronisasi akan memblokir UI untuk sementara waktu. menjaga devtool tetap terbuka dapat memperlambat kinerja pengambilan
Tampilkan cuplikan kode
sumber
createObjectURL
bukannyareadAsDataURL
jauh lebih baik misalnya. Dan jika Anda mengunggah file menggunakan ajax, pilihFormData
sebagai gantinyaJSON
, atau gunakancanvas.toBlob
sebagai gantinyatoDataURL
await (await fetch(imageDataURL)).blob()
await fetch(url).then(r=>r.blob())
penyortirAccess is denied.
kesalahan. Saya kirafetch
mengekspos gumpalan di bawah gumpalan url - dengan cara yang samaURL.createObjectUrl
tidak - yang tidak akan berfungsi pada ie11. referensi . Mungkin ada beberapa solusi untuk menggunakan fetch dengan IE11? Ini terlihat jauh lebih baik daripada solusi sinkronisasi lainnya :)Implementasi yang dioptimalkan (tetapi kurang dapat dibaca):
sumber
Untuk semua dukungan browser, terutama di Android, mungkin Anda dapat menambahkan ini:
sumber
Untuk data gambar, saya merasa lebih mudah digunakan
canvas.toBlob
(asinkron)sumber
image/jpg
dari string base64 dan kemudian meneruskannya sebagai parameter kedua ke dalamtoBlob
fungsi sehingga hasilnya adalah tipe yang sama. Selain itu saya pikir ini sempurna - menghemat 30% dari lalu lintas dan ruang disk Anda di server (dibandingkan dengan base64) dan bekerja dengan baik bahkan dengan PNG transparan.Lihat contoh ini: https://jsfiddle.net/pqhdce2L/
sumber
Saya perhatikan bahwa Internet Explorer 11 menjadi sangat lambat ketika mengiris data seperti yang disarankan Jeremy. Ini berlaku untuk Chrome, tetapi Internet Explorer tampaknya memiliki masalah ketika meneruskan data yang diiris ke Blob-Constructor. Di komputer saya, melewatkan 5 MB data membuat Internet Explorer macet dan konsumsi memori melewati atap. Chrome menciptakan gumpalan dalam waktu singkat.
Jalankan kode ini untuk perbandingan:
Jadi saya memutuskan untuk memasukkan kedua metode yang dijelaskan oleh Jeremy dalam satu fungsi. Kredit pergi kepadanya untuk ini.
sumber
Jika Anda dapat menambahkan satu ketergantungan pada proyek Anda, ada
blob-util
paket npm yang hebat yang menyediakanbase64StringToBlob
fungsi praktis . Setelah ditambahkan ke Anda,package.json
Anda dapat menggunakannya seperti ini:sumber
Untuk semua pecinta salin-tempel di luar sana seperti saya, berikut ini adalah fungsi unduhan matang yang berfungsi di Chrome, Firefox dan Edge:
sumber
createObjectURL
tidak menerima argumen 2 ...Saya memposting cara yang lebih deklaratif untuk sinkronisasi konversi Base64. Walaupun async
fetch().blob()
sangat rapi dan saya sangat menyukai solusi ini, ia tidak bekerja di Internet Explorer 11 (dan mungkin Edge - saya belum menguji yang ini), bahkan dengan polyfill - lihat komentar saya di Endless ' posting untuk lebih jelasnya.Bonus
Jika Anda ingin mencetaknya, Anda dapat melakukan sesuatu seperti:
Bonus x 2 - Membuka file BLOB di tab baru untuk Internet Explorer 11
Jika Anda dapat melakukan preprocessing dari string Base64 di server Anda dapat mengeksposnya di bawah beberapa URL dan menggunakan tautan di
printJS
:)sumber
Berikut ini adalah kode TypeScript saya yang dapat dikonversi dengan mudah menjadi JavaScript dan dapat Anda gunakan
sumber
Typescript code
Kode Anda hanya memiliki tipe TUNGGAL dan tipe ituany
. Seperti kenapa repot-repot ??Metode dengan mengambil adalah solusi terbaik, tetapi jika ada yang perlu menggunakan metode tanpa mengambil maka ini dia, seperti yang disebutkan sebelumnya tidak bekerja untuk saya:
sumber