191

I want to convert Base64String extracted from file(ex: "AAAAA....~") to a javascript file object.

The javascript file object what I mean is like this code:

HTML:

<input type="file" id="selectFile" > 

JS:

$('#selectFile').on('change', function(e) {
  var file = e.target.files[0];

  console.log(file)
}

'file' variable is a javascript file object. So I want to convert a base64 string to the javascript file object like that.

I just want to get file object by decoding base64 string (encoded by other app from a file) without html file input form.

Thank you.

10 Answers 10

342

Way 1: only works for dataURL, not for other types of url.

function dataURLtoFile(dataurl, filename) {
    var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[arr.length - 1]), 
        n = bstr.length, 
        u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, {type:mime});
}

//Usage example:
var file = dataURLtoFile('data:text/plain;base64,aGVsbG8=','hello.txt');
console.log(file);

Way 2: works for any type of url, (http url, dataURL, blobURL, etc...)

// return a promise that resolves with a File instance
function urltoFile(url, filename, mimeType){
    if (url.startsWith('data:')) {
        var arr = url.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[arr.length - 1]), 
            n = bstr.length, 
            u8arr = new Uint8Array(n);
        while(n--){
            u8arr[n] = bstr.charCodeAt(n);
        }
        var file = new File([u8arr], filename, {type:mime || mimeType});
        return Promise.resolve(file);
    }
    return fetch(url)
        .then(res => res.arrayBuffer())
        .then(buf => new File([buf], filename,{type:mimeType}));
}

//Usage example:
urltoFile('data:text/plain;base64,aGVsbG8=', 'hello.txt','text/plain')
.then(function(file){ console.log(file);});

Sign up to request clarification or add additional context in comments.

14 Comments

Warning, it seems to me that File object is only available on Firefox. Prefer Blob objects : developer.mozilla.org/en-US/docs/Web/API/Blob
I use your **2nd way ** to upload pdf thumbnail but, it display black image when upload is done
@ChetanBuddh That may be caused by other issues of your code. Can you paste your code in JSFiddle ?
In way 1, i am getting [object Object] not [object file]. How can i get [object file].@cuixiping
This does not work for the file of format data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQA Could you please let me know if this can be doable? @cuixiping
|
121
const url = 'data:image/png;base6....';
fetch(url)
  .then(res => res.blob())
  .then(blob => {
    const file = new File([blob], "File name",{ type: "image/png" })
  })

Base64 String -> Blob -> File.

3 Comments

Note: This is incompatible with most Content Security Policies, if you have one
@MaxGabriel could you please elaborate?
If you have a CSP with the connect-src attribute to whitelist what URLs your Javascript can load, it will reject it with the error: "Refused to connect to 'data:text/plain;base64,aGVsbG8gd29ybGQ=' because it violates the following Content Security Policy directive: "connect-src <...>". You can have your CSP whitelist data URLs, but MDN warns: "This is insecure; an attacker can also inject arbitrary data: URIs. Use this sparingly and definitely not for scripts." developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
74

This is the latest async/await pattern solution.

export async function dataUrlToFile(dataUrl: string, fileName: string): Promise<File> {

    const res: Response = await fetch(dataUrl);
    const blob: Blob = await res.blob();
    return new File([blob], fileName, { type: 'image/png' });
}

3 Comments

You can get the file type from the base64 url: dataUrl.match(/^data:(.+);base64/)?.[1]
And don't write Response and Blob types. TS will infer them
The only answer that worked for me. In Vue JS I used this code: async dataUrlToFile(dataUrl, fileName){ let res = await fetch(dataUrl) const blob = await res.blob() return new File([blob], fileName, { type: 'image/png' }) }
9

Here is the Typescript version of accepted answer above by @cuixiping, now using Buffer instead of atob()

I saw deprecation warnings using atob() from TypeScript, although it isn't fully deprecated. Only one overload is. However, I converted mine to use the deprecation warning suggestion of Buffer. It seems more clean since it requires no extra loop to convert each character.

  /***
   * Converts a dataUrl base64 image string into a File byte array
   * dataUrl example:
   * data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIsAAACLCAYAAABRGWr/AAAAAXNSR0IA...etc
   */
  dataUrlToFile(dataUrl: string, filename: string): File | undefined {
    const arr = dataUrl.split(',');
    if (arr.length < 2) { return undefined; }
    const mimeArr = arr[0].match(/:(.*?);/);
    if (!mimeArr || mimeArr.length < 2) { return undefined; }
    const mime = mimeArr[1];
    const buff = Buffer.from(arr[1], 'base64');
    return new File([buff], filename, {type:mime});
  }

at the top of the file you'll need an import to make the typings happy.

import { Buffer } from 'buffer';

No special npm packages are needed.

1 Comment

Still works lovely on September 13th 2023. Thank you! If you already have your parsed base64 string, you can just use: const buff = Buffer.from(yourBase64StringContent, "base64"); const fetchedFile = new File([buff], yourDesiredFileName);
8
const file = new File([
  new Blob(["decoded_base64_String"])
], "output_file_name");

You could use a lib like this to decode and encode base64 to arrayBuffer.

4 Comments

It didn't work for me!
works for browser (thanks), does not work for react native (Error: Creating blobs from 'ArrayBuffer' and 'ArrayBufferView' are not supported)
for react-native i use the form data method
type is missing, should be const file = new File([new Blob([base64])], 'pic.png', {type:'image/png'});
8
const base64Str = "AAABAAEAICAAAAAAAACoCAAAFg....AND_SO_ON";
const file = new File(
   [Uint8Array.from(atob(base64Str), (m) => m.codePointAt(0))],
   'myfilename.jpeg',
   { type: "image/jpeg" }
);

1 Comment

This needs some context that explains why it works.
4

I had a very similar requirement (importing a base64 encoded image from an external xml import file. After using xml2json-light library to convert to a json object, I was able to leverage insight from cuixiping's answer above to convert the incoming b64 encoded image to a file object.

const imgName = incomingImage['FileName'];
const imgExt = imgName.split('.').pop();
let mimeType = 'image/png';
if (imgExt.toLowerCase() !== 'png') {
    mimeType = 'image/jpeg';
}
const imgB64 = incomingImage['_@ttribute'];
const bstr = atob(imgB64);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
  u8arr[n] = bstr.charCodeAt(n);
}
const file = new File([u8arr], imgName, {type: mimeType});

My incoming json object had two properties after conversion by xml2json-light: FileName and _@ttribute (which was b64 image data contained in the body of the incoming element.) I needed to generate the mime-type based on the incoming FileName extension. Once I had all the pieces extracted/referenced from the json object, it was a simple task (using cuixiping's supplied code reference) to generate the new File object which was completely compatible with my existing classes that expected a file object generated from the browser element.

Hope this helps connects the dots for others.

Comments

0

Heads up,

JAVASCRIPT

<script>
   function readMtlAtClient(){

       mtlFileContent = '';

       var mtlFile = document.getElementById('mtlFileInput').files[0];
       var readerMTL = new FileReader();

       // Closure to capture the file information.
       readerMTL.onload = (function(reader) {
           return function() {
               mtlFileContent = reader.result;
               mtlFileContent = mtlFileContent.replace('data:;base64,', '');
               mtlFileContent = window.atob(mtlFileContent);

           };
       })(readerMTL);

       readerMTL.readAsDataURL(mtlFile);
   }
</script>

HTML

    <input class="FullWidth" type="file" name="mtlFileInput" value="" id="mtlFileInput" 
onchange="readMtlAtClient()" accept=".mtl"/>

Then mtlFileContent has your text as a decoded string !

Comments

0

Complete Version for Typescript

async uploadImage(b64img: string) {
  var file = await this.urltoFile(b64img,'name.png',this.base64MimeType(b64img));
}

//return a promise that resolves with a File instance
urltoFile(url, filename, mimeType){
    return (fetch(url)
        .then(function(res){return res.arrayBuffer();})
        .then(function(buf){return new File([buf], filename,{type:mimeType});})
    );
}

//return mime Type of bs64
base64MimeType(encoded) {
    var result = null;
  
    if (typeof encoded !== 'string') {
      return result;
    }
  
    var mime = encoded.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/);
  
    if (mime && mime.length) {
      result = mime[1];
    }
  
    return result;
}

Thats Work for me Converting base64 Image to File

Comments

0

this worked for me credit

base64ToFile = (url: string) => {
let arr = url.split(',');
// console.log(arr)
let mime = arr[0].match(/:(.*?);/)![1];
let data = arr[1];

let dataStr = atob(data);
let n = dataStr.length;
let dataArr = new Uint8Array(n);

while (n--) {
  dataArr[n] = dataStr.charCodeAt(n);
}

let file = new File([dataArr], 'File.png', { type: mime });

return file;
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.