Làm cách nào để chuyển đổi tệp sang base64 trong JavaScript?


186

Bây giờ tôi đang nhận đối tượng Tệp theo dòng này:

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

Tôi cần gửi tệp này qua json trong cơ sở 64. Tôi nên làm gì để chuyển đổi nó thành chuỗi base64?

Câu trả lời:


118

Cách ES6 hiện đại (async / 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();

CẬP NHẬT:

Nếu bạn muốn bắt lỗi

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;
   }
   //...
}

Mã này không chính xác. Nếu bạn awaitcó chức năng trả về một Lời hứa bị từ chối, bạn sẽ không nhận được Lỗi do cuộc gọi trả về; nó sẽ bị ném và bạn sẽ cần phải bắt nó.
Dancrumb

1
Ví dụ tuyệt vời về việc sử dụng các chức năng và lời hứa không đồng bộ
Thiago Frias

291

Hãy thử giải pháp bằng cách sử dụng FileReader lớp :

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

Lưu ý rằng đó .files[0]là một Fileloại, là một lớp con của Blob. Vì vậy, nó có thể được sử dụng với FileReader.
Xem ví dụ làm việc hoàn chỉnh .


2
đọc thêm về API FileReader: developer.mozilla.org/en-US/docs/Web/API/FileReader và hỗ trợ trình duyệt: caniuse.com/#feat=filereader
Lukas Liesis

7
Tôi đã cố gắng sử dụng return reader.resulttừ getBase64()chức năng (thay vì sử dụng console.log(reader.result)) vì tôi muốn chụp base64 dưới dạng một biến (và sau đó gửi nó đến Google Apps Script). Tôi đã gọi hàm với: var my_file_as_base64 = getBase64(file)và sau đó cố gắng in ra bàn điều khiển với console.log(my_file_as_base64 )và chỉ cần có undefined. Làm thế nào tôi có thể gán đúng Base64 cho một biến?
dùng1063287

1
Tôi đã đưa ra một câu hỏi trong số các nhận xét trên nếu bất cứ ai có thể trả lời. stackoverflow.com/questions/47195119/
dùng1063287

Tôi cần mở tệp Base64 này trong trình duyệt có cùng tên tệp, tôi đang mở tệp bằng window.open (url, '_blank') đang hoạt động tốt, làm cách nào tôi có thể đặt tên tệp cho nó? xin vui lòng giúp đỡ.
Munish Sharma

Cảm ơn! Tôi nghĩ rằng điều này không được giải thích nhiều trên developer.mozilla.org/en-US/docs/Web/API/FileReader/ chủ
johey

123

Nếu bạn theo đuổi một giải pháp dựa trên lời hứa, đây là mã của @ Dmitri thích nghi với điều đó:

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

Tôi cần mở tệp Base64 này trong trình duyệt có cùng tên tệp, tôi đang mở tệp bằng window.open (url, '_blank') đang hoạt động tốt, làm cách nào tôi có thể đặt tên tệp cho nó? xin vui lòng giúp đỡ.
Munish Sharma

42

Dựa trên các câu trả lời của Dmitri Pavlutin và joshua.paling, đây là phiên bản mở rộng trích xuất nội dung cơ sở64 (loại bỏ siêu dữ liệu lúc đầu) và cũng đảm bảo việc đệm được thực hiện chính xác .

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, thay thế đầu tiên là bắt tệp trống, thay thế thứ hai bị thiếu dấu phẩy - mã hóa = reader.result.replace ("data:", "") .replace (/ ^ .*; base64, /, "");
dùng3333134

Lời nói của tôi, tôi đã bỏ lỡ sự hôn mê đó thực sự. Điều đáng kinh ngạc là dường như nó không làm phiền đến phần phụ trợ của tôi, tôi vẫn có thể tải lên các tệp excel thành công o_O. Tôi cũng đã sửa regex để đưa trường hợp sử dụng tệp trống của bạn vào tài khoản. Cảm ơn.
Arnaud P

2
Tôi đã có một phiên bản thậm chí còn dễ dàng hơn : resolve(reader.result.replace(/^.*,/, ''));. Vì hôn mê ,nằm ngoài bảng chữ cái base64, chúng tôi có thể loại bỏ bất cứ thứ gì xuất hiện cho đến khi và bao gồm cả hôn mê. stackoverflow.com/a/13195218/1935128
Johnride

Ok cảm ơn vì đã ngẩng cao đầu, mặc dù theo regex tôi đã viết ở đây (tôi cần thử nghiệm lại để chắc chắn), có thể data:, không có dấu phẩy, vì vậy tôi sẽ giữ phần đầu tiên như vậy. Tôi đã cập nhật câu trả lời tương ứng.
Arnaud P

1
@ArnaudP Lỗi bản in: Thuộc tính 'thay thế' không tồn tại trên loại 'chuỗi | ArrayBuffer '.
Romel Gomez

12

Javascript btoa () chức năng có thể được sử dụng để chuyển đổi dữ liệu vào chuỗi mã hóa base64


6
btoa chỉ hoạt động với chuỗi. Làm thế nào để sử dụng nó với tập tin?
Vassily

10
bạn sẽ phải đọc tệp trước và sau đó chuyển nó vào chức năng này .. Một cái gì đó như jsfiddle.net/eliseosoto/JHQnk
Pranav Maniar

1
@PranavManiar Fiddle của bạn không còn hoạt động. Bạn có thể cập nhật các liên kết?
Dan

5

Dưới đây là một vài chức năng tôi đã viết để có được một tệp ở định dạng json có thể được chuyển qua một cách dễ dàng:

    //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
Hứa với tất cả, dựa trên một mảng.map hoạt động tuyệt vời! Ít nhất là đối với tôi.
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]);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.