Отримати файлові дані Base64 з форми введення


100

У мене є основна форма HTML, з якої я можу взяти трохи інформації, яку я вивчаю в Firebug.

Єдині мої проблеми - це те, що я намагаюсь базувати кодування файлових даних, перш ніж надсилати їх на сервер, де потрібно бути в цій формі для збереження в базі даних.

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

І в Javascript + jQuery:

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

У мене є кілька операцій на основі доступного javascript: .getAsBinary (), .getAsText (), .getAsTextURL

Однак жоден із цих повернених корисних текстів, які можна вставити, оскільки вони містять непридатні "символи" - я не хочу, щоб у моєму файлі завантажувався "postback", і мені потрібно мати кілька форм, орієнтованих на конкретні об'єкти, тому важливо отримати файл і використовувати 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 would 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, перш ніж він64 кодує? (або порожній рядок)

var encoded = Base64.encode(file); 

Що ви завантажуєте? Текстові дані чи двійкові?
бітгамміт

Бінарні дані @tjamenson - все, що насправді "документ документа", "pdf" "зображення" і т. д. Я збирався призначити ім'я файлу в іншій змінній, але мене почало цікавити, чи маю я якийсь фатальний недолік у розумінні того, що можливо завантажувати форми та html - це метод абсолютно неможливий і неможливо передавати файлові дані, розміщуючи їх як рядок? Також без HTML5, який я читаю, є деякі рішення -
jordan.baucke

Цікаво. Чому ви базуєте 64-кодування між браузером і сервером і намагаєтеся виконати це в браузері? Схоже, якщо ви намагаєтеся захистити дані, SSL було б набагато простіше, оскільки він зашифровує всі дані HTTP (включаючи файли) по дроту. Ви можете базуватись на сервері-64, якщо це потрібно для вашої бази даних.
Вільям Уолсет

@William Я не намагаюся захистити дані, просто переведіть їх у правильний формат. Salesforce.com (платформа Apex) вимагає, щоб база даних, кодована base64, перед створенням запису в базі даних, їх функціональність для базового кодування даних файлів через форму через форму дуже погано зафіксована (я зрозумів, як це зробити після того, як задати це питання). Так чи інакше, схожі на те, що дані бінарних файлів, що кодують base64, підтримуються лише у форматі HTML5 або Mozilla File API
jordan.baucke

1
Гаразд, тепер я бачу, для чого вам це потрібно. Немає проміжного сервера + шалені хмарні вимоги + немає крос-браузерного рішення = 1 безлад. Вибачте.
Вільям Уолсет

Відповіді:


121

Це цілком можливо в JavaScript на стороні браузера.

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

Метод readAsDataURL () може вже кодувати його як base64. Можливо, вам буде потрібно викреслити початкові матеріали (до перших,), але це не є великим. Це зайняло б все задоволення, хоча.

Важкий шлях:

Якщо ви хочете спробувати це важким способом (або він не працює), подивіться readAsArrayBuffer(). Це дасть вам Uint8Array, і ви можете використовувати вказаний метод. Це, мабуть, корисно лише в тому випадку, якщо ви хочете возитися з самими даними, наприклад, маніпулюючи зображеннями зображення або виконуючи інші магії вуду перед завантаженням.

Є два способи:

  • Перетворити на рядок і використовувати вбудований btoa або подібний
    • Я не перевіряв усіх випадків, але працює для мене - просто дістаньте char-коди
  • Перетворити безпосередньо з 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:


чудово - я подумав, що readAsArrayBuffer()виходить як правильні base64 дані, але він не обробляється через випробовувану частину рядка - я зараз знім!
jordan.baucke

1
readAsArrayBuffer (), здається, не існує в Chrome / Safari, і я припускаю, що це буде проблематично в інших браузерах ~ чи є еквівалент, який я можу використовувати в інших браузерах?
jordan.baucke

createObjectURL () <- це виглядає багатообіцяюче, я спробую це здійснити, але я впевнений, що IE знадобиться 3-е колесо
jordan.baucke

Чи можна призначити ім'я файлу перед виконанням рішення для завантаження?
Оммега

@ Ωmega - Ні. Все це - це завантаження двійкового потоку. Немає способу (AFAIK) вказати ім'я файлу. Деякі браузери, однак, здогадуються про розширення. Щоб отримати імена файлів, вам доведеться завантажити та завантажити знову.
beatgammit

37

Моїм рішенням було використання 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');
    };
}

3
На сьогодні найпростіший спосіб, чому це не має більше голосів?
sarink

14

Я використовував 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();
});

1

Сам бореться з цим, я прийшов реалізувати FileReader для браузерів, які його підтримують (Chrome, Firefox та поки що не вийшов Safari 6), і PHP-скрипт, який повторює дані POSTed файлів як кодовані Base64 дані для інших браузери.


0

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


Цікаво, чому ви просто не візьмете [ webtoolkit.info/javascript-base64.html#] , а потім прокоментуйте input = Base64._utf8_encode(input);і output = Base64._utf8_decode(output);? Будь-яка проблема, крім помилки конверсії utf-8?
shr

@shr Я не знаю, як захопити дані бінарних файлів для введення цих методів у кожному браузері? $('#inputid').files[0](не працює в IE7, наскільки я можу сказати ). Якби це було так просто? var output = Base64.encode($('#inputid').files[0])??
jordan.baucke

0

Натхненний відповіддю @ Йозефа:

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