Як можна перетворити зображення в рядок Base64 за допомогою JavaScript?


500

Мені потрібно перетворити своє зображення в рядок Base64, щоб я могла надсилати своє зображення на сервер.

Чи є для цього файл JavaScript? Ще, як я можу це перетворити?


5
Звідки походить ваше зображення?
TJHeuvel


Відповіді:


182

Ви можете використовувати HTML5 <canvas>для цього:

Створіть полотно, завантажте в нього своє зображення, а потім використовуйте toDataURL()для отримання представлення Base64 (насправді це data:URL-адреса, але вона містить зображення, закодоване Base64).


3
Чи toDataURLдає контроль над зворотними done/fail/alwaysдзвінками, як, наприклад, xhr?
Jeroen

Чи можемо ми витягти 2 або більше полотна як один PNG?
techie_28

139
Чи можете ви, будь ласка, зробити jsbin або хоча б написати якийсь код тут?
vsync

9
Такий підхід виявляється невдалим у випадку порушення CORS. Крім цього, це рішення має вирішити питання.
Revanth Kumar


851

Можна вибрати кілька підходів:

1. Підхід: FileReader

Завантажте зображення як blob через XMLHttpRequest і використовуйте API FileReader для перетворення його в даніURL :

function toDataURL(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      callback(reader.result);
    }
    reader.readAsDataURL(xhr.response);
  };
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.send();
}

toDataURL('https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0', function(dataUrl) {
  console.log('RESULT:', dataUrl)
})

Цей приклад коду також може бути реалізований за допомогою API завантаження WHATWG :

const toDataURL = url => fetch(url)
  .then(response => response.blob())
  .then(blob => new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(blob)
  }))


toDataURL('https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0')
  .then(dataUrl => {
    console.log('RESULT:', dataUrl)
  })

Ці підходи:

  • відсутність підтримки браузера
  • мають кращу компресію
  • працювати і для інших типів файлів

Підтримка браузера:


2. Підхід: полотно

Завантажте зображення у зображення-об’єкт, намалюйте його на нестандартне полотно та перетворіть полотно назад у даніURL.

function toDataURL(src, callback, outputFormat) {
  var img = new Image();
  img.crossOrigin = 'Anonymous';
  img.onload = function() {
    var canvas = document.createElement('CANVAS');
    var ctx = canvas.getContext('2d');
    var dataURL;
    canvas.height = this.naturalHeight;
    canvas.width = this.naturalWidth;
    ctx.drawImage(this, 0, 0);
    dataURL = canvas.toDataURL(outputFormat);
    callback(dataURL);
  };
  img.src = src;
  if (img.complete || img.complete === undefined) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
  }
}

toDataURL(
  'https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0',
  function(dataUrl) {
    console.log('RESULT:', dataUrl)
  }
)

Детально

Підтримувані формати введення:

image/png, image/jpeg, image/jpg, image/gif, image/bmp, image/tiff, image/x-icon, image/svg+xml, image/webp,image/xxx

Підтримувані формати виводу:

image/png, image/jpeg, image/webp(Хром)

Підтримка браузера:

  • http://caniuse.com/#feat=canvas
  • Internet Explorer 10 (Internet Explorer 10 просто працює з зображеннями з однаковим походженням)


3. Підхід: зображення з локальної файлової системи

Якщо ви хочете перетворити зображення з файлової системи користувачів, вам слід застосувати інший підхід. Використовуйте API FileReader :

function encodeImageFileAsURL(element) {
  var file = element.files[0];
  var reader = new FileReader();
  reader.onloadend = function() {
    console.log('RESULT', reader.result)
  }
  reader.readAsDataURL(file);
}
<input type="file" onchange="encodeImageFileAsURL(this)" />


56
Не працює в хромі для мене:Image from origin **** has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fiddle.jshell.net' is therefore not allowed access.
DickieBoy

5
Про всяк випадок, якщо це відключає когось іншого вгору, цей порядок включає заголовок "data: image / jpg; base64" у рядку, який він повертає, тому вам не потрібно додавати це.
Кріс Рай

1
Warnin2: щось змішується зі змістом. десь по дорозі, є ймовірність, що дані будуть пошкоджені / змінені (навіть якщо, можливо, не набагато), принаймні, це трапляється зі мною на Firefox 35 на деяких зображеннях, base64 відрізняється від base64, що php створює на тих же зображення.
hanshenrik

1
Так це правильно. Деякі дані можуть загубитися, оскільки ми фактично малюємо зображення на полотні Element ( developer.mozilla.org/en-US/docs/Web/API/… ), а потім перетворюємо їх у даніURL ( developer.mozilla.org/en- США / docs / Web / API / HTMLCanvasElement /… ).
HaNdTriX

1
Підхід: FileReader (2) працює швидше, ніж підходить до Canvas. Тестували на великих фотографіях. Сподіваюся, це буде корисним для когось.
Макс

83

Цей фрагмент може конвертувати ваш рядок, зображення та навіть відео файл у рядкові дані Base64.

<input id="inputFileToLoad" type="file" onchange="encodeImageFileAsURL();" />
<div id="imgTest"></div>
<script type='text/javascript'>
  function encodeImageFileAsURL() {

    var filesSelected = document.getElementById("inputFileToLoad").files;
    if (filesSelected.length > 0) {
      var fileToLoad = filesSelected[0];

      var fileReader = new FileReader();

      fileReader.onload = function(fileLoadedEvent) {
        var srcData = fileLoadedEvent.target.result; // <--- data: base64

        var newImage = document.createElement('img');
        newImage.src = srcData;

        document.getElementById("imgTest").innerHTML = newImage.outerHTML;
        alert("Converted Base64 version is " + document.getElementById("imgTest").innerHTML);
        console.log("Converted Base64 version is " + document.getElementById("imgTest").innerHTML);
      }
      fileReader.readAsDataURL(fileToLoad);
    }
  }
</script>


3
Це не тільки чудово, але це також обходить проблему походження кросдомена! За допомогою цього ви можете дозволити користувачам надсилати власні зображення чи зображення з URL-адреси (оскільки Windows отримає їх самостійно), намалювати їх на полотні та працювати з ними, поки ще може використовувати .toDataURL () тощо. Дуже дякую!
ElDoRado1239

Привіт, як це можна застосувати до зображення, завантаженого з віддаленої URL-адреси, не стикаючись з проблемами між домену? Дякую
guthik

Іноді це працює в Chrome 78.0.3904.97, але в іншому випадку він перериває вкладку.
Дшиз

28

В основному, якщо ваше зображення є

<img id='Img1' src='someurl'>

тоді ви можете конвертувати її як би

var c = document.createElement('canvas');
var img = document.getElementById('Img1');
c.height = img.naturalHeight;
c.width = img.naturalWidth;
var ctx = c.getContext('2d');

ctx.drawImage(img, 0, 0, c.width, c.height);
var base64String = c.toDataURL();

5
На жаль, це спрацює лише для локальних зображень, якщо ви спробуєте його, використовуючи віддалене зображення (виберіть одне з Інтернету), воно записує це на (firefox) консоль: "SecurityError: Операція небезпечна".
user2677034

1
Це може працювати на інших зображеннях, але це залежить від налаштувань CORS цього сайту та має бути вказане як<img id='Img1' src='someurl' crossorigin='anonymous'>
Майк

У Firefox ви можете тимчасово відключити цю безпеку. Перейдіть на "about: config" та змініть властивість "privacy.file_unique_origin" на false
Мануель Ромейро

21

Ось що я зробив:

// Author James Harrington 2014
function base64(file, callback){
  var coolFile = {};
  function readerOnload(e){
    var base64 = btoa(e.target.result);
    coolFile.base64 = base64;
    callback(coolFile)
  };

  var reader = new FileReader();
  reader.onload = readerOnload;

  var file = file[0].files[0];
  coolFile.filetype = file.type;
  coolFile.size = file.size;
  coolFile.filename = file.name;
  reader.readAsBinaryString(file);
}

А ось як ви цим користуєтеся

base64( $('input[type="file"]'), function(data){
  console.log(data.base64)
})

6
що таке бтоа? :)
Олександр Міллс


14

Я виявив, що найбезпечніший і надійний спосіб це зробити - це використовувати FileReader().

Демонстрація: Зображення на Base64

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <input id="myinput" type="file" onchange="encode();" />
    <div id="dummy">
    </div>
    <div>
      <textarea style="width:100%;height:500px;" id="txt">
      </textarea>
    </div>
    <script>
      function encode() {
        var selectedfile = document.getElementById("myinput").files;
        if (selectedfile.length > 0) {
          var imageFile = selectedfile[0];
          var fileReader = new FileReader();
          fileReader.onload = function(fileLoadedEvent) {
            var srcData = fileLoadedEvent.target.result;
            var newImage = document.createElement('img');
            newImage.src = srcData;
            document.getElementById("dummy").innerHTML = newImage.outerHTML;
            document.getElementById("txt").value = document.getElementById("dummy").innerHTML;
          }
          fileReader.readAsDataURL(imageFile);
        }
      }
    </script>
  </body>
</html>

6

Якщо у вас є об’єкт файлу, ця проста функція буде працювати:

function getBase64 (file, callback) {

    const reader = new FileReader();

    reader.addEventListener('load', () => callback(reader.result));

    reader.readAsDataURL(file);
}

Приклад використання:

getBase64(fileObjectFromInput, function(base64Data){
    console.log("Base64 of file is", base64Data); // Here you can have your code which uses Base64 for its operation, // file to Base64 by oneshubh
});


4

Наскільки мені відомо, зображення можна перетворити в рядок Base64 або FileReader (), або зберегти його в елементі canvas, а потім використовувати toDataURL (), щоб отримати зображення. У мене були подібні проблеми, з якими ви можете звернутися до цього.

Перетворіть зображення на вже завантажене полотно


4

Спробуйте цей код:

Для події зміни файлу завантажте файл:

$("#fileproof").on('change', function () {
    readImage($(this)).done(function (base64Data) { $('#<%=hfimgbs64.ClientID%>').val(base64Data); });
});

function readImage(inputElement) {
    var deferred = $.Deferred();

    var files = inputElement.get(0).files;

    if (files && files[0]) {
        var fr = new FileReader();
        fr.onload = function (e) {
            deferred.resolve(e.target.result);
        };
        fr.readAsDataURL(files[0]);
    } else {
        deferred.resolve(undefined);
    }

    return deferred.promise();
}

Зберігайте дані Base64 у прихованому файлі для використання.


1
Привіт Раві! Я бачу, ви відносно нові. Якщо оригінальний плакат спеціально не вимагає рішення для бібліотеки, таких як jQuery, lodash тощо, краще всім відповісти, використовуючи голосні мінімуми, в цьому випадку звичайний javascript. Якщо ви все ще хочете внести свій внесок у jQuery, будь ласка, уточніть це у своєму записі :)
Carles Alcolea


0

Що ж, якщо ви використовуєте інструментарій Dojo Toolkit , це дає нам прямий спосіб кодування або декодування в Base64.

Спробуйте це:

Для кодування масиву байтів за допомогою dojox.encoding.base64:

var str = dojox.encoding.base64.encode(myByteArray);

Для декодування рядка, кодованого Base64:

var bytes = dojox.encoding.base64.decode(str);

2
@DownVoter - Шановний, краще вказати на помилку також, якщо ви відзначаєте щось негативне. щоб хтось міг покращитись. наскільки я розумію доджо також у бібліотеці JavaScript, тоді, якщо вам дозволено використовувати dojo, ви точно можете використовувати такий підхід.
Вікаш Пандей
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.