【问题标题】:How to decode a base64 string properly in javascript如何在javascript中正确解码base64字符串
【发布时间】:2019-11-30 01:14:54
【问题描述】:

我尝试将使用 FileReader.readAsDataURL() 从 pdf 文件生成的 base64 字符串转换为其原始格式。
在 NodeJS 中我这样做了,它能够将 pdf 生成为其初始状态。

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

但我尝试在this way 中用 HTML + Javascript 来做。但是这样,pdf 是空的/没有字母不在里面

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

我正在以这种方式捕获文件并转换为base64字符串:

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

然后单击按钮后,我将缓冲区添加到 IPFS 节点

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

使用IPFS HASH我可以取回base64编码的字符串,我以这种方式检索了这个字符串:

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

我使用了Truffle Petshop 并将这些函数写在它上面。这是一个 IPFS 哈希 QmfSefUiwjV44hpfnHyUngGATyHm9M4vN3PzF1mpe59Nn1。您可以使用此代码在 nodejs 中尝试此哈希值

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

您可以找到完整代码here。 我做错了什么以及如何解决?

【问题讨论】:

  • stringval 是硬编码字符串还是从文件读取器调用中获取的?如果是后者,您需要在文件读取器 onload 或 onloadend 事件中执行所有操作。您也可以在这里使用blob 而不是file,例如URL.createObjectURL(blob)。显示minimal reproducible example,这样我们就可以正确地看到发生了什么
  • 我认为使用 base64 编码写入文件实际上与调用 atob 函数相反
  • 是后者,来自 filereader 调用。获得 base64 字符串后,我将其上传到 IPFS 文件(ipfs.io)。使用 IPFS 哈希我可以取回 base64 字符串。我试图将其转换为同一个文件
  • 我想我添加了我完成的大部分程序,还添加了一个 nodejs 代码,用于测试 IPFS 哈希并区分结果。我应该更详细地说明我的代码吗..? @PatrickEvans
  • 这行不通Buffer.from("base64string", "base64").toString("utf8");

标签: javascript node.js file base64


【解决方案1】:

使用 atob() 转换 base64 string 后,我将其转换为 Uint8Array 然后创建了 blob 和文件。它现在似乎工作..

这里是完整的代码:

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

【讨论】:

  • 你比较过校验和吗?我通过 JS 和我从 js 生成的文件测试了一些东西,这些文件与我用 php 编码的原始文件不同。我的步骤:原始文件 => base64 with php => 通过 ajax 将字符串发送到 js,用 js 解码
  • 我检查了 sha256 并且他们匹配
猜你喜欢
  • 2019-07-30
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多