1

I am trying to create a file object from a base64 image which was cut from another image. I am able to do it but the resulting file size is almost thrice the actual size. Below is the function that I am using:

convertDataURItoFile(dataURI, fileName) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    var byteString = atob(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);

    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    // write the ArrayBuffer to a blob, and you're done
    var blob: any = new Blob([ia], { type: mimeString });

    //A Blob() is almost a File() - it's just missing the two properties below which we will add
    blob.lastModifiedDate = new Date();
    blob.name = fileName;
    //Cast to a File() type
    return <File>blob;
  }

Any idea on why the file size increasing so drastically? How can I compress it? Thanks in advance.

2
  • "the resulting file size is almost thrice the actual size" How did you determine that the size of resulting Blob is a different size? If you want to set .name and .lastModifiedDate why do you not use File constructor? File inherits from Blob, Blob does not inherit from File. Commented Apr 26, 2017 at 16:21
  • Cannot reproduce resulting Blob which has .size greater than content of data URI passed. Though note, resulting Blob is not the same data content as passed data URI. Can you create a stacksnippets or plnkr plnkr.co to demonstrate "the resulting file size is almost thrice the actual size"? See stackoverflow.com/help/mvce Commented Apr 26, 2017 at 16:46

1 Answer 1

3

I am trying to create a file object from a base64 image which was cut from another image. I am able to do it but the resulting file size is almost thrice the actual size.

Cannot reproduce resulting .size of Blob being thrice the size of the content of input data URI. Do you mean the data URI .length can be thrice the size of Blob .size?

function convertDataURItoFile(dataURI, fileName) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    var byteString = atob(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);

    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    // write the ArrayBuffer to a blob, and you're done
    var blob = new Blob([ia], { type: mimeString });

    //A Blob() is almost a File() - it's just missing the two properties below which we will add
    blob.lastModifiedDate = new Date();
    blob.name = fileName;
    //Cast to a File() type
    console.log(`input data size: ${datauriLength} Blob.size: ${blob.size}`);
    return blob;
  }
  
const [datauri, filename] = ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASoAAADCCAYAAAD+Wo90AAAABHNCSVQICAgIfAhkiAAAApVJREFUeJzt1DEBACAMwLCBf88ggZMeiYJeXTPnDEDY/h0A8GJUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkHcBRH8DgsmlTc8AAAAASUVORK5CYII=", "filename.png"];

const datauriLength = datauri.length;

const reader = new FileReader;
reader.onload = () => {
  console.log(`data URI: ${reader.result}`)
  document.querySelector("iframe").src = reader.result;
};

reader.readAsDataURL(convertDataURItoFile(datauri, filename));
<iframe></iframe>

If .name and .lastModifiedDate need to be added to Blob, you can substitute using File constructor for Blob, which expects file name parameter to be set at second parameter to File constructor, and optionally expected .lastModidied and or .lastModifiedDate parameters at third parameter to constructor.

function convertDataURItoFile(dataURI, fileName) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    var byteString = atob(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);

    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    // write the ArrayBuffer to a blob, and you're done
    // use `File` constructor here
    var blob = new File([ia], fileName, { type: mimeString, lastModifiedDate: new Date() });

    //A Blob() is almost a File() - it's just missing the two properties below which we will add
    // blob.lastModifiedDate = new Date();
    // blob.name = fileName;
    //Cast to a File() type
    console.log(`input data size: ${datauriLength} Blob.size: ${blob.size}`);
    return blob;
  }
  
const [datauri, filename] = ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASoAAADCCAYAAAD+Wo90AAAABHNCSVQICAgIfAhkiAAAApVJREFUeJzt1DEBACAMwLCBf88ggZMeiYJeXTPnDEDY/h0A8GJUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkGdUQJ5RAXlGBeQZFZBnVECeUQF5RgXkGRWQZ1RAnlEBeUYF5BkVkHcBRH8DgsmlTc8AAAAASUVORK5CYII=", "filename.png"];

const datauriLength = datauri.length;

const reader = new FileReader;
reader.onload = () => {
  console.log(`data URI: ${reader.result}`)
  document.querySelector("iframe").src = reader.result;
};

reader.readAsDataURL(convertDataURItoFile(datauri, filename));
<iframe></iframe>

You can also utilize fetch() to create and get Blob representation of data URI, see Answer by @Endless at Creating a Blob from a base64 string in JavaScript

Not the answer you're looking for? Browse other questions tagged or ask your own question.