UPD TypeScript版本也可在答案

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

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

我需要通过json在基数64发送这个文件。我应该怎么做才能将其转换为base64字符串?


当前回答

现代ES6路(异步/await)

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];
   try {
      const result = await toBase64(file);
      return result
   } catch(error) {
      console.error(error);
      return;
   }
   //...
}

其他回答

现代ES6路(异步/await)

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];
   try {
      const result = await toBase64(file);
      return result
   } catch(error) {
      console.error(error);
      return;
   }
   //...
}

在德米特里·帕夫卢汀和乔舒亚的基础上。下面是一个扩展版本,它提取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);
  });
}

如果你在寻找一个基于承诺的解决方案,这是@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)
);

通过添加扩展上述解决方案,并在需要的地方添加用例 能够遍历表单上的多个字段并获取它们的值 其中一个是文件,它导致了异步需求的问题

解决方法如下:

    async collectFormData() {
        // Create the file parsing promise
        const toBase64 = file => new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => resolve(reader.result);
            reader.onerror = error => reject(error);
        });
    
        
        let form_vals = []
        let els = [] // Form elements collection

        // This is separate because wrapping the await in a callback
        // doesn't work 
        $(`.form-field`).each(function (e) {
            els.push(this) // add to the collection of form fields
        })

        // Loop through the fields to collect information 
        for (let elKey in els) {
            let el = els[elKey]

            // If the field is input of type file. call the base64 parser
            if ($(el).attr('type') == 'file') {
                // Get a reference to the file
                const file = el.files[0];

                form_vals.push({
                    "key": el.id,
                    "value": await toBase64(file)
                })

        }


        // TODO: The rest of your code here form_vals will now be 
        // populated in time for a server post
    }

这纯粹是为了解决处理多个字段的问题 以一种更流畅的方式

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