【问题标题】:How to convert file to base64 in JavaScript?如何在 JavaScript 中将文件转换为 base64?
【发布时间】:2016-07-16 19:16:20
【问题描述】:

UPDTypeScript 版本也可在答案中找到

现在我通过这一行获取 File 对象:

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

我需要通过base 64中的json发送这个文件。我应该怎么做才能将它转换为base64字符串?

【问题讨论】:

    标签: javascript base64


    【解决方案1】:

    JavaScriptbtoa()函数可用于将数据转换为base64编码字符串

    <div>
        <div>
            <label for="filePicker">Choose or drag a file:</label><br>
            <input type="file" id="filePicker">
        </div>
        <br>
        <div>
            <h1>Base64 encoded version</h1>
            <textarea id="base64textarea" 
                      placeholder="Base64 will appear here" 
                      cols="50" rows="15"></textarea>
        </div>
    </div>
    
    var handleFileSelect = function(evt) {
        var files = evt.target.files;
        var file = files[0];
    
        if (files && file) {
            var reader = new FileReader();
    
            reader.onload = function(readerEvt) {
                var binaryString = readerEvt.target.result;
                document.getElementById("base64textarea").value = btoa(binaryString);
            };
    
            reader.readAsBinaryString(file);
        }
    };
    
    if (window.File && window.FileReader && window.FileList && window.Blob) {
        document.getElementById('filePicker')
                .addEventListener('change', handleFileSelect, false);
    } else {
        alert('The File APIs are not fully supported in this browser.');
    }
    

    【讨论】:

    • btoa 仅适用于字符串。如何与文件一起使用?
    • 你必须先读取文件,然后将它传递给这个函数。像jsfiddle.net/eliseosoto/JHQnk
    • @PranavManiar 你的小提琴不再奏效了。你能更新链接吗?
    【解决方案2】:

    使用FileReader class 尝试解决方案:

    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一起使用。
    查看完整的工作example

    【讨论】:

    • 详细了解 FileReader API:developer.mozilla.org/en-US/docs/Web/API/FileReader 和浏览器支持:caniuse.com/#feat=filereader
    • 我尝试使用getBase64() 函数中的return reader.result(而不是使用console.log(reader.result)),因为我想将base64 捕获为变量(然后将其发送到Google Apps 脚本)。我用var my_file_as_base64 = getBase64(file) 调用了这个函数,然后尝试用console.log(my_file_as_base64 ) 打印到控制台,结果得到了undefined。如何正确地将 base64 分配给变量?
    • 如果有人可以回答,我从上述评论中提出了一个问题。 stackoverflow.com/questions/47195119/…
    • 我需要在浏览器中使用相同的文件名打开这个 Base64 文件,我使用 window.open(url, '_blank') 打开它,它工作正常,我怎样才能给文件名那 ?请帮忙。
    • 谢谢!我认为developer.mozilla.org/en-US/docs/Web/API/FileReader/… 上没有很好地解释这一点
    【解决方案3】:

    如果您寻求基于承诺的解决方案,这是@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') 打开它,它工作正常,我怎样才能给文件名那 ?请帮忙。
    【解决方案4】:

    这是我编写的几个函数,用于获取可以轻松传递的 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);
    

    【讨论】:

    • 承诺所有,基于 array.map 效果很好!至少对我来说。
    【解决方案5】:

    在 Dmitri Pavlutin 和 joshua.paling 的答案的基础上,这是一个扩展版本,它提取 base64 内容(删除开头的元数据)并确保 padding is done correctly

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

    【讨论】:

    • Chrome 69,第一次替换是抓空文件,第二次替换是缺少逗号-coded = reader.result.replace("data:", "").replace(/^.*; base64,/, "");
    • 我的话,我确实错过了昏迷。令人难以置信的是,它似乎根本没有打扰我的后端,我仍然能够成功上传excel文件o_O。我已经修复了正则表达式,以将您的空文件用例也考虑在内。谢谢。
    • 我有一个更简单的版本:resolve(reader.result.replace(/^.*,/, ''));。由于 coma , 在 base64 字母表之外,我们可以删除任何出现的内容,直到包括 coma 在内。 stackoverflow.com/a/13195218/1935128
    • 好的,谢谢提醒,虽然根据我在这里写的正则表达式(我需要再次试验才能确定),可能只有data:,没有任何逗号,所以我'将保持第一部分不变。我已经相应地更新了答案。
    • @ArnaudP Typescript 错误:“字符串 | 类型”上不存在属性“替换”数组缓冲区'。
    【解决方案6】:

    现代 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();
    

    更新:

    如果你想捕捉错误

    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,你不会得到调用返回的错误;它会被抛出,你需要抓住它。
    • 使用异步函数和承诺的好例子
    • 我实际上尝试了这个 sn-p 试图转换 上的图像并得到一个错误。 : Users.js:41 Uncaught (in promise) TypeError: 无法在“FileReader”上执行“readAsDataURL”:参数 1 不是“Blob”类型。
    【解决方案7】:
    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]);
        }
    }
    

    【讨论】:

      【解决方案8】:

      我用过这个简单的方法,效果很好

       function  uploadImage(e) {
        var file = e.target.files[0];
          let reader = new FileReader();
          reader.onload = (e) => {
          let image = e.target.result;
          console.log(image);
          };
        reader.readAsDataURL(file);
        
      }
      

      【讨论】:

        【解决方案9】:

        TypeScript 版本

        const file2Base64 = (file:File):Promise<string> => {
            return new Promise<string> ((resolve,reject)=> {
                 const reader = new FileReader();
                 reader.readAsDataURL(file);
                 reader.onload = () => resolve(reader.result?.toString() || '');
                 reader.onerror = error => reject(error);
             })
            }
        

        【讨论】:

        • reader.result 可能为空,并且会出现打字稿错误。此代码处理这种情况:reader.onload = () =&gt; resolve(reader.result ? reader.result.toString() : '')
        • 为了防止Object is possibly 'null' 错误,您可以使用像reader.onload = () =&gt; resolve(reader.result?.toString() || '');这样的可选链接运算符
        • 谢谢,我更新了代码:)
        【解决方案10】:
        const fileInput = document.querySelector('input');
        
        fileInput.addEventListener('change', (e) => {
        
        // get a reference to the file
        const file = e.target.files[0];
        
        // encode the file using the FileReader API
        const reader = new FileReader();
        reader.onloadend = () => {
        
            // use a regex to remove data url part
            const base64String = reader.result
                .replace('data:', '')
                .replace(/^.+,/, '');
        
            // log to console
            // logs wL2dvYWwgbW9yZ...
            console.log(base64String);
        };
        reader.readAsDataURL(file);});
        

        【讨论】:

        【解决方案11】:

        使用这种方式将任何文件转换为base64 -

        _fileToBase64(file: File) {
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => resolve(reader.result.toString().substr(reader.result.toString().indexOf(',') + 1));
            reader.onerror = error => reject(error);
          });
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-07
          • 1970-01-01
          相关资源
          最近更新 更多