Base64 convert back to file

Hi guys. So in front end I have this piece of code.

uploadCallback (file) {
    // TODO: Integrate dropbox with its SDK
    // TODO: Pass the link to the editor
    console.log('file', file)
    this.getBase64(file, this)
  }
  getBase64 (file, self) {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = function () {
      console.log('reader.result', reader.result)
      self.sendFileToServer(reader.result)
    }
    reader.onerror = function (error) {
      console.log('Error: ', error)
    }
  }
  sendFileToServer (base64File) {
    return new Promise(
      (resolve, reject) => {
        console.log('uploadCallback promise')
        Meteor.call('uploadToDropbox', base64File, function (error, result) {
          console.log('uploadToDropbox callback')
          if (error) {
            console.log('error', error)
          }
          if (result) {
            console.log('result', result)
          }
        })
      }
    )
  }

It takes the file object converts to base64 and passes to a called method. And in the server here is my method

import { Meteor } from 'meteor/meteor'
import Dropbox from 'dropbox'
// import atob from 'atob'
import FileAPI from 'file-api'

const { File } = FileAPI

console.log('dropbox settings', Meteor.settings.dropbox)
const dbx = new Dropbox({accessToken: Meteor.settings.dropbox.accessToken})

Meteor.methods({
  'uploadToDropbox': function (base64File) {
    console.log('base64File', base64File.slice(5))
    const b64 = base64File.split(',')
    const name = `${Math.random().toString(36).slice(-5)}.png`
    const file = new File({buffer: new Buffer(b64[1]), name, type: 'image/png'})
    console.log('file', file)
    dbx.filesUpload({path: '/' + file.name, contents: file.buffer})
      .then(function (response) {
        console.log(response)
      })
      .catch(function (error) {
        console.error('dropbox error', error)
      })
    return false
  }
})

Here I try to convert the base64File back to file object and upload it to dropbox. In the back end I use this package https://github.com/node-file-api/file-api

Now here everything seems to be working. The file is being successfully uploaded to the dropbox. However the image itself is empty. And when I download the uploaded image from the dropbox and open it in my computer, the viewer says the file is not a png. So probably my file is not being converted correctly.
So how can I convert the base64File back to a normal file?

Here is what I have used in the past, borrowed from this thread:

const convertBase64ToFile = function (image) {
  const byteString = atob(image.split(',')[1]);
  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);
  for (let i = 0; i < byteString.length; i += 1) {
    ia[i] = byteString.charCodeAt(i);
  }
  const newBlob = new Blob([ab], {
    type: 'image/jpeg',
  });
  return newBlob;
};

Hi dear @vigorwebsolutions thank you for your reply!

Here is a simpler solution

const i = base64File.indexOf('base64,');
const buffer = Buffer.from(base64File.slice(i + 7), 'base64');
const file = new File({buffer: buffer, name, type: 'image/png'});

So the full code would be

import { Meteor } from 'meteor/meteor'
import Dropbox from 'dropbox'
import FileAPI from 'file-api'

const { File } = FileAPI

console.log('dropbox settings', Meteor.settings.dropbox)
const dbx = new Dropbox({accessToken: Meteor.settings.dropbox.accessToken})

Meteor.methods({
  'uploadToDropbox': function (base64File) {
    console.log('base64File', base64File.slice(5))
    const i = base64File.indexOf('base64,')
    const buffer = Buffer.from(base64File.slice(i + 7), 'base64')
    const name = `${Math.random().toString(36).slice(-5)}.png`
    const file = new File({buffer, name, type: 'image/png'})
    console.log('file', file)
    dbx.filesUpload({path: '/' + file.name, contents: file.buffer})
      .then(function (response) {
        console.log(response)
      })
      .catch(function (error) {
        console.error('dropbox error', error)
      })
    return false
  }
})
1 Like