Bagaimana cara mengonversi file ke base64 di JavaScript?

186

Sekarang saya mendapatkan objek File dengan baris ini:

file = document.querySelector('#files > input[type="file"]').files[0]

Saya perlu mengirim file ini melalui json di basis 64. Apa yang harus saya lakukan untuk mengubahnya menjadi string base64?

Dengan lantang
sumber

Jawaban:

118

Cara ES6 modern (async / menunggu)

const toBase64 = file => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
});

async function Main() {
   const file = document.querySelector('#myfile').files[0];
   console.log(await toBase64(file));
}

Main();

UPD:

Jika Anda ingin menangkap kesalahan

async function Main() {
   const file = document.querySelector('#myfile').files[0];
   const result = await toBase64(file).catch(e => Error(e));
   if(result instanceof Error) {
      console.log('Error: ', result.message);
      return;
   }
   //...
}
Дмитрий Васильев
sumber
Kode ini salah. Jika Anda awaitsuatu fungsi yang mengembalikan Janji yang ditolak, Anda tidak akan mendapatkan Kesalahan yang dikembalikan oleh panggilan; itu akan dibuang dan Anda harus menangkapnya.
Dancrumb
1
Contoh bagus penggunaan fungsi dan janji async
Thiago Frias
292

Coba solusinya menggunakan FileReader kelas :

function getBase64(file) {
   var reader = new FileReader();
   reader.readAsDataURL(file);
   reader.onload = function () {
     console.log(reader.result);
   };
   reader.onerror = function (error) {
     console.log('Error: ', error);
   };
}

var file = document.querySelector('#files > input[type="file"]').files[0];
getBase64(file); // prints the base64 string

Perhatikan bahwa itu .files[0]adalah Filetipe, yang merupakan sub dari dari Blob. Dengan demikian dapat digunakan dengan FileReader.
Lihat contoh kerja lengkap .

Dmitri Pavlutin
sumber
2
baca lebih lanjut tentang FileReader API: developer.mozilla.org/en-US/docs/Web/API/FileReader dan dukungan browser: caniuse.com/#feat=filereader
Lukas Liesis
7
Saya mencoba menggunakan return reader.resultdari getBase64()fungsi (daripada menggunakan console.log(reader.result)) karena saya ingin menangkap base64 sebagai variabel (dan kemudian mengirimkannya ke Google Apps Script). Saya memanggil fungsi dengan: var my_file_as_base64 = getBase64(file)dan kemudian mencoba mencetak ke konsol dengan console.log(my_file_as_base64 )dan baru saja undefined. Bagaimana cara menetapkan base64 dengan benar ke variabel?
user1063287
1
Saya membuat pertanyaan dari komentar di atas jika ada yang bisa menjawab. stackoverflow.com/questions/47195119/…
user1063287
Saya perlu membuka file Base64 ini di browser dengan nama file yang sama, saya membukanya menggunakan window.open (url, '_blank') yang berfungsi dengan baik, bagaimana saya bisa memberikan nama file untuk itu? tolong bantu.
Munish Sharma
Terima kasih! Saya pikir ini tidak dijelaskan dengan baik di developer.mozilla.org/en-US/docs/Web/API/FileReader/…
johey
123

Jika Anda mencari solusi berbasis janji, ini adalah kode @ Dmitri yang disesuaikan untuk itu:

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

var file = document.querySelector('#files > input[type="file"]').files[0];
getBase64(file).then(
  data => console.log(data)
);
joshua.paling
sumber
Saya perlu membuka file Base64 ini di browser dengan nama file yang sama, saya membukanya menggunakan window.open (url, '_blank') yang berfungsi dengan baik, bagaimana saya bisa memberikan nama file untuk itu? tolong bantu.
Munish Sharma
42

Membangun pada Dmitri Pavlutin dan joshua.paling menjawab, inilah versi yang diperpanjang yang mengekstrak konten base64 (menghapus metadata di awal) dan juga memastikan bantalan dilakukan dengan benar .

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      let encoded = reader.result.toString().replace(/^data:(.*,)?/, '');
      if ((encoded.length % 4) > 0) {
        encoded += '='.repeat(4 - (encoded.length % 4));
      }
      resolve(encoded);
    };
    reader.onerror = error => reject(error);
  });
}
Arnaud P
sumber
2
Chrome 69, ganti pertama adalah untuk menangkap file kosong, ganti kedua hilang koma - dikodekan = reader.result.replace ("data:", "") .replace (/^.*; base64, /, "" ");
user3333134
Kata saya, saya memang merindukan koma itu. Yang luar biasa adalah sepertinya tidak mengganggu backend saya sama sekali, saya masih dapat mengunggah file excel dengan sukses o_O. Saya telah memperbaiki regex untuk memasukkan case use file kosong Anda ke dalam akun juga. Terima kasih.
Arnaud P
2
Aku punya versi lebih mudah: resolve(reader.result.replace(/^.*,/, ''));. Karena koma ,berada di luar alfabet base64, kita dapat menghapus apa pun yang muncul sampai dan termasuk koma. stackoverflow.com/a/13195218/1935128
Johnride
Ok terima kasih untuk kepala, meskipun menurut regex yang saya tulis di sini (saya perlu bereksperimen lagi untuk memastikan), mungkin saja ada data:, tanpa koma, jadi saya akan menjaga bagian pertama seperti apa adanya. Saya telah memperbarui jawabannya.
Arnaud P
1
@ArnaudP Kesalahan skrip: Properti 'ganti' tidak ada pada tipe 'string | ArrayBuffer '.
Romel Gomez
12

Fungsi JavaScript btoa () dapat digunakan untuk mengubah data menjadi string yang disandikan base64

Pranav Maniar
sumber
6
Btoa hanya bekerja dengan string. Bagaimana cara menggunakannya dengan file?
Vassily
10
Anda harus membaca file terlebih dahulu dan kemudian meneruskannya ke fungsi ini .. Sesuatu seperti jsfiddle.net/eliseosoto/JHQnk
Pranav Maniar
1
@PranavManiar Biola Anda tidak lagi berfungsi. Bisakah Anda memperbarui tautannya?
Dan
5

Berikut adalah beberapa fungsi yang saya tulis untuk mendapatkan file dalam format json yang dapat diedarkan dengan mudah:

    //takes an array of JavaScript File objects
    function getFiles(files) {
        return Promise.all(files.map(file => getFile(file)));
    }

    //take a single JavaScript File object
    function getFile(file) {
        var reader = new FileReader();
        return new Promise((resolve, reject) => {
            reader.onerror = () => { reader.abort(); reject(new Error("Error parsing file"));}
            reader.onload = function () {

                //This will result in an array that will be recognized by C#.NET WebApi as a byte[]
                let bytes = Array.from(new Uint8Array(this.result));

                //if you want the base64encoded file you would use the below line:
                let base64StringFile = btoa(bytes.map((item) => String.fromCharCode(item)).join(""));

                //Resolve the promise with your custom file structure
                resolve({ 
                    bytes: bytes,
                    base64StringFile: base64StringFile,
                    fileName: file.name, 
                    fileType: file.type
                });
            }
            reader.readAsArrayBuffer(file);
        });
    }

    //using the functions with your file:

    file = document.querySelector('#files > input[type="file"]').files[0]
    getFile(file).then((customJsonFile) => {
         //customJsonFile is your newly constructed file.
         console.log(customJsonFile);
    });

    //if you are in an environment where async/await is supported

    files = document.querySelector('#files > input[type="file"]').files
    let customJsonFiles = await getFiles(files);
    //customJsonFiles is an array of your custom files
    console.log(customJsonFiles);
tkd_aj
sumber
1
Berjanjilah semua, berbasis di array.map berfungsi dengan baik! Setidaknya untuk saya.
davidwillianx
0
onInputChange(evt) {
    var tgt = evt.target || window.event.srcElement,
    files = tgt.files;
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            var base64 = fr.result;
            debugger;
        }
        fr.readAsDataURL(files[0]);
    }
}
pengguna2120895
sumber