Як конвертувати файл в base64 в JavaScript?


186

Тепер я отримую об'єкт File за цим рядком:

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

Мені потрібно надіслати цей файл через json в базі 64. Що мені робити, щоб перетворити його в рядок base64?

Відповіді:


118

Сучасний спосіб ES6 (асинхронізація / очікування)

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:

Якщо ви хочете виявити помилки

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;
   }
   //...
}

Цей код невірний. Якщо у вас awaitфункція, яка повертає відхилену Обіцянку, ви не отримаєте Помилку, повернуту викликом; вона буде кинута, і вам потрібно буде її зловити.
Dancrumb

1
Чудовий приклад використання функцій та обіцянок асинхронізації
Thiago Frias

292

Спробуйте рішення за допомогою FileReader класу :

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

Зауважте, що .files[0]це Fileтип, який є підрозділом Blob. Таким чином, його можна використовувати з FileReader.
Дивіться повний робочий приклад .


2
читайте більше про API FileReader: developer.mozilla.org/en-US/docs/Web/API/FileReader та підтримка браузера: caniuse.com/#feat=filereader
Лукас Лієсіс

7
Я намагався використовувати return reader.resultцю getBase64()функцію (а не використовувати console.log(reader.result)), тому що я хочу захопити base64 як змінну (а потім надіслати її до сценарію Google Apps). Я зателефонував до функції:, var my_file_as_base64 = getBase64(file)а потім спробував надрукувати для консолі console.log(my_file_as_base64 )та щойно отримав undefined. Як я можу правильно призначити base64 змінної?
user1063287

1
Я поставив запитання з вищевказаного коментаря, якщо хтось може відповісти. stackoverflow.com/questions/47195119 / ...
user1063287

Мені потрібно відкрити цей файл Base64 у веб-переглядачі з тим самим ім'ям файлу, я відкриваю його за допомогою window.open (url, '_blank'), який працює нормально, як я можу надати ім'я цього файлу? будь ласка, допоможіть.
Муніш Шарма

Дякую! Я думаю, що це не дуже добре пояснено на developer.mozilla.org/en-US/docs/Web/API/FileReader/…
johey

123

Якщо ви вирішили базуватись на обіцянках, це код @ Дмитра, пристосований для цього:

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

Мені потрібно відкрити цей файл Base64 у веб-переглядачі з тим самим ім'ям файлу, я відкриваю його за допомогою window.open (url, '_blank'), який працює нормально, як я можу надати ім'я цього файлу? будь ласка, допоможіть.
Муніш Шарма

42

Створюючи відповіді на Дмитра Павлутіна та joshua.paling, ось розширена версія, яка витягує вміст base64 (видаляє метадані на початку), а також забезпечує правильне виконання роботи .

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);
  });
}

2
Chrome 69, перша заміна полягає у виловленні порожнього файлу, у другій заміні відсутня кома - закодовано = reader.result.replace ("дані:", "") .replace (/^.*; base64, /, "");
користувач3333134

Моє слово, я дійсно пропустив цю кому. Що неймовірно, це те, що це, схоже, не турбувало мій бекенд, я все-таки змогла успішно завантажувати файли Excel o_O. Я виправив регекс, щоб врахувати і ваш порожній випадок використання файлів. Дякую.
Арно Р

2
У мене є ще простіший варіант: resolve(reader.result.replace(/^.*,/, ''));. Оскільки кома ,знаходиться за межами алфавіту base64, ми можемо зняти все, що з’явиться до коми, включаючи кому. stackoverflow.com/a/13195218/1935128
Johnride

Ок, дякую за голову вгору, хоча згідно з написаним тут регексом (мені потрібно буде ще раз експериментувати, щоб бути впевненим), може бути просто data:, без жодної коми, тому я буду тримати цю першу частину як є. Відповідно я оновив відповідь.
Арно П

1
@ArnaudP Typescript помилка: Властивість 'substitute' не існує у рядку type ' ArrayBuffer '.
Ромель Гомес

12

Функцію JavaScript btoa () можна використовувати для перетворення даних у кодовану рядок base64


6
btoa працює лише з рядком. Як використовувати його з файлом?
Василь

10
вам доведеться спочатку прочитати файл, а потім передати його цій функції. Щось на зразок jsfiddle.net/eliseosoto/JHQnk
Pranav Maniar

1
@PranavManiar Ваша загадка більше не працює. Чи можете ви оновити посилання?
Ден

5

Ось кілька функцій, які я написав, щоб отримати файл у форматі json, який можна легко передати:

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

1
Обіцяйте всі, що базується на array.map чудово працює! Принаймні для мене.
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]);
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.