Получить Base64 кодировать файл-данные из формы ввода

У меня есть базовая HTML-форма, из которой я могу получить немного информации, которую я изучаю в Firebug.

Моя единственная проблема заключается в том, что я пытаюсь с помощью base64 кодировать данные файла, прежде чем они будут отправлены на сервер, где они должны быть в этой форме для сохранения в базе данных.

<input type="file" id="fileupload" />

И в Javascript+jQuery:

var file = $('#fileupload').attr("files")[0];

У меня есть некоторые операции, основанные на доступных JavaScript: .getAsBinary (),.getAsText (),.getAsTextURL

Однако ни один из них не возвращает пригодный для использования текст, который можно вставить, так как он содержит непригодные "символы" - я не хочу, чтобы в моем загруженном файле возникала "обратная передача", и мне нужно иметь несколько форм, нацеленных на конкретные объекты, поэтому важно, чтобы я получить файл и использовать Javascript таким образом.

Как мне получить файл таким образом, чтобы я мог использовать один из широко распространенных кодировщиков Javascript base64!?

Спасибо

Обновление - Начиная здесь щедрость, нужна поддержка кросс-браузера!!!

Вот где я нахожусь:

<input type="file" id="fileuploadform" />

<script type="text/javascript>
var uploadformid = 'fileuploadform';
var uploadform = document.getElementById(uploadformid);


/* method to fetch and encode specific file here based on different browsers */

</script>

Пара проблем с кросс-браузерной поддержкой:

var file = $j(fileUpload.toString()).attr('files')[0];
fileBody = file.getAsDataURL(); // only works in Firefox

Кроме того, IE не поддерживает:

var file = $j(fileUpload.toString()).attr('files')[0];

Поэтому я должен заменить на:

var element = 'id';
var element = document.getElementById(id);

Для поддержки IE.

Это работает в Firefox, Chrome, Safari (но не правильно кодирует файл, или, по крайней мере, после того, как он был опубликован, файл выходит неправильно)

var file = $j(fileUpload.toString()).attr('files')[0];
var encoded = Btoa(file);

Также,

file.readAsArrayBuffer() 

Кажется, поддерживается только в HTML5?

Многие люди предложили: http://www.webtoolkit.info/javascript-base64.html

Но это только возвращает ошибку en в методе UTF_8 до того, как кодирует base64? (или пустая строка)

var encoded = Base64.encode(file); 

8 ответов

Решение

Это вполне возможно в браузерном JavaScript.

Простой способ:

Метод readAsDataURL() может уже закодировать его как base64 для вас. Вам, вероятно, нужно будет удалить начальный материал (до первого), но это не важно. Это бы вывело все самое интересное.

Трудный путь:

Если вы хотите попробовать это трудным путем (или он не работает), посмотрите на readAsArrayBuffer(), Это даст вам Uint8Array, и вы сможете использовать указанный метод. Это, вероятно, полезно только в том случае, если вы хотите связываться с самими данными, например манипулировать данными изображения или выполнять другую магию вуду перед загрузкой.

Есть два метода:

  • Конвертировать в строку и использовать встроенный btoa или похожие
    • Я не проверял все случаи, но работает на меня - просто получите коды
  • Конвертировать напрямую из Uint8Array в base64

Я недавно реализовал tar в браузере. В рамках этого процесса я создал собственную прямую реализацию Uint8Array->base64. Я не думаю, что вам это понадобится, но это здесь, если вы хотите посмотреть; это довольно опрятно.

Что я делаю сейчас:

Код для преобразования в строку из Uint8Array довольно прост (где buf - это Uint8Array):

function uint8ToString(buf) {
    var i, length, out = '';
    for (i = 0, length = buf.length; i < length; i += 1) {
        out += String.fromCharCode(buf[i]);
    }
    return out;
}

Оттуда просто сделайте:

var base64 = btoa(uint8ToString(yourUint8Array));

Base64 теперь будет строкой в ​​кодировке base64, и она должна загружаться просто замечательно. Попробуйте это, если хотите дважды проверить перед нажатием:

window.open("data:application/octet-stream;base64," + base64);

Это загрузит это как файл.

Другая информация:

Чтобы получить данные в виде Uint8Array, посмотрите документы MDN:

Мое решение было использовать readAsBinaryString() а также btoa() на его результат.

uploadFileToServer(event) {
    var file = event.srcElement.files[0];
    console.log(file);
    var reader = new FileReader();
    reader.readAsBinaryString(file);

    reader.onload = function() {
        console.log(btoa(reader.result));
    };
    reader.onerror = function() {
        console.log('there are some problems');
    };
}

Я использовал FileReader для отображения изображения при нажатии кнопки загрузки файла, не используя Ajax-запросы. Ниже приведен код, который может помочь кому-то.

$(document).ready(function($) {
    $.extend( true, jQuery.fn, {        
        imagePreview: function( options ){          
            var defaults = {};
            if( options ){
                $.extend( true, defaults, options );
            }
            $.each( this, function(){
                var $this = $( this );              
                $this.bind( 'change', function( evt ){

                    var files = evt.target.files; // FileList object
                    // Loop through the FileList and render image files as thumbnails.
                    for (var i = 0, f; f = files[i]; i++) {
                        // Only process image files.
                        if (!f.type.match('image.*')) {
                        continue;
                        }
                        var reader = new FileReader();
                        // Closure to capture the file information.
                        reader.onload = (function(theFile) {
                            return function(e) {
                                // Render thumbnail.
                                    $('#imageURL').attr('src',e.target.result);                         
                            };
                        })(f);
                        // Read in the image file as a data URL.
                        reader.readAsDataURL(f);
                    }

                });
            });
        }   
    });
    $( '#fileinput' ).imagePreview();
});

Вдохновленный ответом @Josef:

const fileToBase64 = async (file) =>
  new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (e) => reject(e)
  })

const file = event.srcElement.files[0];
const imageStr = await fileToBase64(file)

Полный пример

Ввод файла HTML

      <style>
.upload-button {
  background-color: grey;
}

.upload-button input{
  display:none;
}
</style>
<label for="upload-photo" class="upload-button">
    Upload file
    <input
     type="file"
     id="upload-photo"
    </input>
</label>

Обработчик JS

      document.getElementById("upload-photo").addEventListener("change", function({target}){
 if (target.files && target.files.length) {
      try {
        const uploadedImageBase64 = await convertFileToBase64(target.files[0]); 
        //do something with above data string 
      } catch() {
        //handle error
      }
    }
})

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

После этого я сам решил реализовать FileReader для браузеров, которые его поддерживают (Chrome, Firefox и пока не выпущенный Safari 6), и сценарий PHP, который возвращает данные файла POST в виде данных в кодировке Base64 для других браузеры.

Так почему же вы не соглашаетесь с пользователем системы на выбор изображения из известной папки? Или они могут установить свою папку для изображений.

Большинство браузеров не поддерживают полный путь, но вы можете получить имя файла, например, "image.png"

Использование встроенной функции PHP для кодирования:

      @$picture_base64 = base64_encode( file_get_contents($image_file_name)  );

Знак @ подавляет ошибку, если путь не найден, но результат будет нулевым для переменной $picture_base64, поэтому я думаю, что вы в порядке с нулевым значением, как я еще проверяю значение нуля, прежде чем продолжить.

В html вы можете выбрать имя файла изображения для ввода, например, «image.png» (но не полный путь)

      <input type="file" name="image" id="image" >

Затем в PHP вы можете сделать:

      $path = "C:\\users\\john\\Desktop\\images\\"
@$picture_base64 = base64_encode( file_get_contents( $path. $_POST['image']);

Тогда $picture_base64 будет выглядеть примерно так

      "AQAAAAMAAAAHAAAADwAAAB8AAAA/AAAAfwAAAP8AAAD/AQAA/w"

Я начал думать, что использование iframe для загрузки в стиле Ajax может быть гораздо лучшим выбором для моей ситуации, пока HTML5 не пройдет полный цикл, и мне не придется поддерживать устаревшие браузеры в моем приложении!

Другие вопросы по тегам