Как я могу преобразовать изображение в строку Base64, используя JavaScript?

501

Мне нужно преобразовать мое изображение в строку Base64, чтобы я мог отправить свое изображение на сервер.

Есть ли файл JavaScript для этого? Иначе, как я могу преобразовать это?

Coder_sLaY
источник
5
Откуда ваш образ?
TJHeuvel
1
JS и jQ : stackoverflow.com/questions/17710147/…
Роко Бульян

Ответы:

182

Вы можете использовать HTML5 <canvas>для этого:

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

ThiefMaster
источник
3
Дает ли toDataURLконтроль над обратными вызовами, такими как done/fail/alwaysв случае с xhr?
Йерун
Можем ли мы извлечь 2 или более холста как один PNG?
techie_28
141
Можете ли вы сделать jsbin или хотя бы написать код здесь?
vsync
9
Этот подход не работает в случае нарушения CORS. Кроме того, это решение должно решить вопрос.
Ревант Кумар
Вот пакет npm для него
user3517175
853

Есть несколько подходов, которые вы можете выбрать:

1. Подход: FileReader

Загрузите изображение как blob через XMLHttpRequest и используйте FileReader API, чтобы преобразовать его в dataURL :

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. Подход: холст

Загрузите изображение в Image-Object, нарисуйте его на необработанном холсте и преобразуйте холст обратно в dataURL.

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

HaNdTriX
источник
56
Не работает в Chrome для меня: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/... ) , а затем преобразовать его в dataURL ( developer.mozilla.org/en- US / 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, но в других случаях происходит сбой вкладки.
Dshiz
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'>
Mike
В 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)
})
Джеймс Харрингтон
источник
7
что такое бтоа? :)
Александр Миллс
4
a = ASCII и b = Binary stackoverflow.com/questions/33854103/…
Джеймс Харрингтон
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>
jonathana
источник
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
});
Shubham
источник
5

Вы можете использовать FileAPI , но он практически не поддерживается.

Артем Тихомиров
источник
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
3
uploadProfile(e) {

    let file = e.target.files[0];
    let reader = new FileReader();

    reader.onloadend = function() {
        console.log('RESULT', reader.result)
    }
    reader.readAsDataURL(file);
}
Махеди Хасан Дурджой
источник
0

Что ж, если вы используете Dojo Toolkit , это дает нам прямой способ кодировать или декодировать в Base64.

Попробуй это:

Чтобы кодировать массив байтов с помощью dojox.encoding.base64:

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

Чтобы декодировать строку в кодировке Base64:

var bytes = dojox.encoding.base64.decode(str);
Викаш Пандей
источник
2
@DownVoter - Уважаемый, лучше указывать на ошибку, даже если вы отмечаете что-то негативное. так что кто-то может улучшить. насколько я понимаю, dojo также и в библиотеке JavaScript, поэтому, если вам разрешено использовать dojo, вы определенно можете использовать этот подход.
Викаш Пандей