1

I tried to convert a base64 string generated from pdf file using FileReader.readAsDataURL() to its original format.
In NodeJS I did it like this and it was able generated the pdf to its initial state.

filebuffer = "data:application/pdf;base64,JVBERi0xLjQKJSDi48/..........."
let base64file = fileBuffer.split(';base64,').pop();
fs.writeFileSync('download.pdf',base64file,{encoding:'base64'},function(err){
    if(err === null){
        console.log("file created");
        return;
    }
    else{
        console.log(err);
        return;
    }
})

But i tried to do it in HTML + Javascript in this way.But in this way , pdf was empty/no letter wasn't in it

let stringval = "data:application/pdf;base64,JVBERi0xLjQKJSDi48/..........."
let encodedString = stringval.split(';base64,').pop();

let data = atob(encodedString);
let blob = new Blob([data]);

// //if you need a literal File object
let file = new File([blob], "filename");

link.href = URL.createObjectURL(file);
link.download = 'filename';

I was Capturing file and converting to base64 string in this way:

captureFile: function () {
event.preventDefault();
const file = event.target.files[0];
$("#labelinput1").html(file.name);
const reader = new window.FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
  var x = reader.result.toString();
  App.buffer2 = x;
  console.log("buffer", App.buffer);
};}

Then after clicking a button , I added the buffer to IPFS node

addfile: async function () {
if (App.buffer2 === null) return;
App.node = await window.Ipfs.create()
App.node.add(App.buffer2, function (errx, resipfs) {
      if (errx === null) {
        console.log(resipfs[0].hash);
        App.buffer2 = null;
        return App.showInfo(resipfs[0].hash);
      }
      else {
        return App.showError(errx.message.toString() + errx.stack.toString());
      }
    });
}

using the IPFS HASH i can get back the base64 encoded string , I retrieved this string in this way:

ipfsfiledownload: async function () {
var filebuffer = await App.node.cat(hashtext);
var stringval = filebuffer.toString();
//convert this string to main file
}

I used Truffle Petshop and write those functions in top of it. Here is a IPFS hash QmfSefUiwjV44hpfnHyUngGATyHm9M4vN3PzF1mpe59Nn1. you can try out this Hash value in nodejs with this code

const IPFS = require('ipfs');
const fs = require('fs');
const main = async() => {
    const node = await IPFS.create()
    var fileBuffer = await 
    node.cat('QmfSefUiwjV44hpfnHyUngGATyHm9M4vN3PzF1mpe59Nn1')
    fileBuffer = fileBuffer.toString()
    let base64file = fileBuffer.split(';base64,').pop();
    fs.writeFileSync('download.pdf',base64file, {encoding:'base64'},function(err){
        if(err === null){
            console.log("file created");
            return;
        }
        else{
            console.log(err);
            return;
        }
    })
}

main()

You can find the full code here. What I am doing wrong and how to solve it?

Dharman
  • 30,962
  • 25
  • 85
  • 135
sabertooth
  • 582
  • 1
  • 7
  • 23
  • Is `stringval` a hard coded string or are you getting it from the filereader calls? If it is the latter you need to do all that in the filereader onload or onloadend event. Also you can use the `blob` instead of `file` here, eg `URL.createObjectURL(blob)`. Show a [mcve] so we can properly see what is going on – Patrick Evans Nov 30 '19 at 01:52
  • I think writing to file with base64 encoding is actualy the opposite of calling atob function – Haijin Nov 30 '19 at 02:46
  • It is the latter, from filereader calls. After I got the base64 String i uploaded it to IPFS Files(https://ipfs.io). Using IPFS hash i can get back the base64 string . I was trying to convert it to the same file – sabertooth Nov 30 '19 at 07:21
  • I think I added the most of the procedure I done and also added a nodejs code to I used to test the IPFS hash and differentiate the result. Should I detail my code more ..? @PatrickEvans – sabertooth Nov 30 '19 at 08:00
  • wouldn't this work `Buffer.from("base64string", "base64").toString("utf8");` – Ashish Modi Nov 30 '19 at 15:30

1 Answers1

2

After converting the base64 string using atob() , I converted it to Uint8Array Then created the blob and file . It seems to work now ..

Here is the full code :

ipfsfiledownload: async function () {
    var hashtext = document.getElementById("id_ipfshash").value //getting the IPFS HASH
    var link = document.getElementById("downloadLink"); 
    if (hashtext === null) return
    var filebuffer = await App.node.cat(hashtext); //getting the base64 string from IPFS
    var stringval = filebuffer.toString();

    console.log(stringval);
    let encodedString = stringval.split(',')[1]; //getting the base64 hash
    let mimetype = stringval.split(',')[0].split(':')[1].split(';')[0]; //getting the mime type

    let data = atob(encodedString); //ascii to binary
    var ab = new ArrayBuffer(data.length); 
    var ia = new Uint8Array(ab);
    //converting to Uint8Array
    for(var i = 0;i<data.length;i++){
          ia[i] = data.charCodeAt(i);
    }
    let blob = new Blob([ia],{ "type": mimetype});
    let filename = 'filename.' + App.getExtension(mimetype);
    let file = new File([blob], filename);

    link.href = window.URL.createObjectURL(file);
    link.download = filename;
    link.click();
}
sabertooth
  • 582
  • 1
  • 7
  • 23
  • do u compared the Checksums? i tested something with offers downlods over JS and my generated files from js where different to the orginal files i encoded with php. My steps: orginal file => base64 with php => send the string over ajax to js, decoded with js – StefanBD Nov 30 '19 at 16:10
  • 1
    I checked with sha256 and they matched – sabertooth Nov 30 '19 at 16:32