[javascript] Get Base64 encode file-data from Input Form

I've got a basic HTML form from which I can grab a bit of information that I'm examining in Firebug.

My only issues is that I'm trying to base64 encode the file data before it's sent to the server where it's required to be in that form to be saved to the database.

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

And in Javascript+jQuery:

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

I have some operations based on available javascript: .getAsBinary(), .getAsText(), .getAsTextURL

However none of these return usable text that can be inserted as they contain unusable 'characters' - I don't want to have a 'postback' occur in my file uploaded, and I need to have multiple forms targeting specific objects so it's important I get the file and use Javascript this way.

How should I get the file in such a way that I can use one of the Javascript base64 encoders that are widely available!?

Thanks

Update - Starting bounty here, need cross-browser support!!!

Here is where I'm at:

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

Couple of issues with cross browser support:

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

Also, IE doesn't support:

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

So I have to replace with:

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

For IE Support.

This works in Firefox, Chrome and, Safari (but doesn't properly encode the file, or at least after it's been posted the file doesn't come out right)

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

Also,

file.readAsArrayBuffer() 

Seems to be only supported in HTML5?

Lots of people suggested: http://www.webtoolkit.info/javascript-base64.html

But this only returns an error on the UTF_8 method before it base64 encodes? (or an empty string)

var encoded = Base64.encode(file); 

This question is related to javascript html file-upload base64

The answer is


It's entirely possible in browser-side javascript.

The easy way:

The readAsDataURL() method might already encode it as base64 for you. You'll probably need to strip out the beginning stuff (up to the first ,), but that's no biggie. This would take all the fun out though.

The hard way:

If you want to try it the hard way (or it doesn't work), look at readAsArrayBuffer(). This will give you a Uint8Array and you can use the method specified. This is probably only useful if you want to mess with the data itself, such as manipulating image data or doing other voodoo magic before you upload.

There are two methods:

  • Convert to string and use the built-in btoa or similar
    • I haven't tested all cases, but works for me- just get the char-codes
  • Convert directly from a Uint8Array to base64

I recently implemented tar in the browser. As part of that process, I made my own direct Uint8Array->base64 implementation. I don't think you'll need that, but it's here if you want to take a look; it's pretty neat.

What I do now:

The code for converting to string from a Uint8Array is pretty simple (where buf is a 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;
}

From there, just do:

var base64 = btoa(uint8ToString(yourUint8Array));

Base64 will now be a base64-encoded string, and it should upload just peachy. Try this if you want to double check before pushing:

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

This will download it as a file.

Other info:

To get the data as a Uint8Array, look at the MDN docs:


I used FileReader to display image on click of the file upload button not using any Ajax requests. Following is the code hope it might help some one.

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

Inspired by @Josef's answer:

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)

My solution was use readAsBinaryString() and btoa() on its result.

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

After struggling with this myself, I've come to implement FileReader for browsers that support it (Chrome, Firefox and the as-yet unreleased Safari 6), and a PHP script that echos back POSTed file data as Base64-encoded data for the other browsers.


I've started to think that using the 'iframe' for Ajax style upload might be a much better choice for my situation until HTML5 comes full circle and I don't have to support legacy browsers in my app!


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to file-upload

bootstrap 4 file input doesn't show the file name How to post a file from a form with Axios File Upload In Angular? How to set the max size of upload file The request was rejected because no multipart boundary was found in springboot Send multipart/form-data files with angular using $http File upload from <input type="file"> How to upload files in asp.net core? REST API - file (ie images) processing - best practices Angular - POST uploaded file

Examples related to base64

How to convert an Image to base64 string in java? How to convert file to base64 in JavaScript? How to convert Base64 String to javascript file object like as from file input form? How can I encode a string to Base64 in Swift? ReadFile in Base64 Nodejs Base64: java.lang.IllegalArgumentException: Illegal character Converting file into Base64String and back again Convert base64 string to image How to encode text to base64 in python Convert base64 string to ArrayBuffer