如何在JavaScript中将文件转换为base64?


186

现在,我通过此行获取File对象:

file = document.querySelector('#files > input[type="file"]').files[0]

我需要在base 64中通过json发送此文件。如何将其转换为base64字符串?

Answers:


118

现代ES6方式(异步/等待)

const toBase64 = file => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
});

async function Main() {
   const file = document.querySelector('#myfile').files[0];
   console.log(await toBase64(file));
}

Main();

UPD:

如果您想捕捉错误

async function Main() {
   const file = document.querySelector('#myfile').files[0];
   const result = await toBase64(file).catch(e => Error(e));
   if(result instanceof Error) {
      console.log('Error: ', result.message);
      return;
   }
   //...
}

该代码不正确。如果您await的函数返回了被拒绝的Promise,则调用不会返回错误。它会被抛出,您需要抓住它。
Dancrumb

1
使用异步函数和
Promise的一个

292

使用FileReader 尝试解决方案:

function getBase64(file) {
   var reader = new FileReader();
   reader.readAsDataURL(file);
   reader.onload = function () {
     console.log(reader.result);
   };
   reader.onerror = function (error) {
     console.log('Error: ', error);
   };
}

var file = document.querySelector('#files > input[type="file"]').files[0];
getBase64(file); // prints the base64 string

请注意,这.files[0]是一种File类型,是的子类Blob。因此可以与结合使用FileReader
请参阅完整的工作示例


2
了解有关FileReader API的更多信息:developer.mozilla.org/en-US/docs/Web/API/FileReader和浏览器支持:caniuse.com/#feat=filereader
Lukas Liesis

7
我试图return reader.resultgetBase64()函数中使用(而不是使用console.log(reader.result)),因为我想将base64捕获为变量(然后将其发送到Google Apps脚本)。我用调用了函数:var my_file_as_base64 = getBase64(file),然后尝试使用进行打印到console console.log(my_file_as_base64 )并得到了undefined。如何正确地将base64分配给变量?
user1063287 '17

1
如果有人可以回答,我就以上评论提出了一个问题。 stackoverflow.com/questions/47195119/...
user1063287

我需要在浏览器中以相同的文件名打开此Base64文件,我正在使用window.open(url,'_blank')正常工作,如何给它命名文件?请帮忙。
穆尼沙玛(Munish Sharma)'18 -4-26


123

如果您追求基于承诺的解决方案,那么这是@Dmitri的适用于此的代码:

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

var file = document.querySelector('#files > input[type="file"]').files[0];
getBase64(file).then(
  data => console.log(data)
);

我需要在浏览器中以相同的文件名打开此Base64文件,我正在使用window.open(url,'_blank')正常工作,如何给它命名文件?请帮忙。
Munish Sharma

42

在Dmitri Pavlutin和joshua.paling答案的基础上,这是扩展版本,可提取base64内容(删除开头的元数据)并确保填充正确完成

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      let encoded = reader.result.toString().replace(/^data:(.*,)?/, '');
      if ((encoded.length % 4) > 0) {
        encoded += '='.repeat(4 - (encoded.length % 4));
      }
      resolve(encoded);
    };
    reader.onerror = error => reject(error);
  });
}

2
Chrome 69,第一个替换是捕获空文件,第二个替换是缺少逗号-编码= reader.result.replace(“ data:”,“”).replace(/^.*; base64,/,“”);
user3333134 '18

我的话,我的确确实想念那昏迷。令人难以置信的是,它似乎根本没有打扰我的后端,我仍然能够成功上传o_O的excel文件。我已经修复了正则表达式,以考虑您的空文件用例。谢谢。
Arnaud P

2
我有一个更简单的版本:resolve(reader.result.replace(/^.*,/, ''));。由于昏迷,在base64字母之外,因此我们可以剥离出现的所有内容,直到并包括昏迷。stackoverflow.com/a/13195218/1935128
Johnride '19

好的,谢谢大家的注意,尽管根据我在这里写的正则表达式(我需要再次尝试才能确定),可能只是存在data:,没有任何逗号,因此我将第一部分保持不变。我已经相应地更新了答案。
Arnaud P

1
@ArnaudP Typescript错误:类型'string |不存在属性'replace' ArrayBuffer”。
罗密尔·戈麦斯


5

这是我编写的几个函数,用于获取可以轻松传递的json格式的文件:

    //takes an array of JavaScript File objects
    function getFiles(files) {
        return Promise.all(files.map(file => getFile(file)));
    }

    //take a single JavaScript File object
    function getFile(file) {
        var reader = new FileReader();
        return new Promise((resolve, reject) => {
            reader.onerror = () => { reader.abort(); reject(new Error("Error parsing file"));}
            reader.onload = function () {

                //This will result in an array that will be recognized by C#.NET WebApi as a byte[]
                let bytes = Array.from(new Uint8Array(this.result));

                //if you want the base64encoded file you would use the below line:
                let base64StringFile = btoa(bytes.map((item) => String.fromCharCode(item)).join(""));

                //Resolve the promise with your custom file structure
                resolve({ 
                    bytes: bytes,
                    base64StringFile: base64StringFile,
                    fileName: file.name, 
                    fileType: file.type
                });
            }
            reader.readAsArrayBuffer(file);
        });
    }

    //using the functions with your file:

    file = document.querySelector('#files > input[type="file"]').files[0]
    getFile(file).then((customJsonFile) => {
         //customJsonFile is your newly constructed file.
         console.log(customJsonFile);
    });

    //if you are in an environment where async/await is supported

    files = document.querySelector('#files > input[type="file"]').files
    let customJsonFiles = await getFiles(files);
    //customJsonFiles is an array of your custom files
    console.log(customJsonFiles);

1
保证一切,基于array.map效果很好!至少对于我来说。
davidwillianx

0
onInputChange(evt) {
    var tgt = evt.target || window.event.srcElement,
    files = tgt.files;
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            var base64 = fr.result;
            debugger;
        }
        fr.readAsDataURL(files[0]);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.