วิธีแปลงไฟล์เป็น base64 ใน JavaScript


186

ตอนนี้ฉันได้รับวัตถุไฟล์โดยบรรทัดนี้:

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

ฉันต้องส่งไฟล์นี้ผ่าน json ใน base 64 ฉันควรทำอย่างไรเพื่อแปลงเป็น base64 string

คำตอบ:


118

Modern ES6 way (async / คอย)

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เป็นฟังก์ชันที่ส่งคืนสัญญาที่ถูกปฏิเสธคุณจะไม่ได้รับข้อผิดพลาดที่ส่งคืนโดยการโทร มันจะถูกโยนทิ้งและคุณจะต้องจับมัน
Dancrumb

1
ตัวอย่างที่ดีของการใช้ฟังก์ชั่นและสัญญา async
Thiago Frias

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ชนิดซึ่งเป็น sublcass Blobของ FileReaderดังนั้นมันจึงสามารถใช้กับ
ดูการทำงานที่สมบูรณ์ตัวอย่างเช่น


2
อ่านเพิ่มเติมเกี่ยวกับ FileReader API: developer.mozilla.org/en-US/docs/Web/API/FileReaderและการสนับสนุนเบราว์เซอร์: caniuse.com/#feat=filereader
Lukas Liesis

7
ฉันพยายามใช้return reader.resultจากgetBase64()ฟังก์ชั่น (แทนที่จะใช้console.log(reader.result)) เพราะฉันต้องการจับ base64 เป็นตัวแปร (แล้วส่งไปที่ Google Apps Script) ผมเรียกว่าฟังก์ชั่นที่มี: var my_file_as_base64 = getBase64(file)แล้วพยายามที่จะพิมพ์ไปยังคอนโซลด้วยและเพียงแค่มีconsole.log(my_file_as_base64 ) undefinedฉันจะกำหนด base64 ให้กับตัวแปรได้อย่างไร
user1063287

1
ฉันทำคำถามจากความคิดเห็นข้างต้นหากใครสามารถตอบ stackoverflow.com/questions/47195119/…
user1063287

ฉันจำเป็นต้องเปิดไฟล์ Base64 นี้ในเบราว์เซอร์ที่มีชื่อไฟล์เหมือนกันฉันกำลังเปิดไฟล์โดยใช้ window.open (url, '_blank') ซึ่งใช้งานได้ดีฉันจะให้ชื่อไฟล์นั้นได้อย่างไร กรุณาช่วย.
Munish Sharma

ขอบคุณ! ฉันคิดว่านี่ไม่ได้อธิบายได้ดีนัก
......

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

คำพูดของฉันฉันคิดถึงอาการโคม่านั้นจริง ๆ สิ่งที่เหลือเชื่อคือมันไม่ได้รบกวนแบ็คเอนด์ของฉันเลยฉันยังสามารถอัปโหลดไฟล์ excel ได้อย่างประสบความสำเร็จ o_O ฉันได้แก้ไข regex ให้คำนึงถึงกรณีการใช้ไฟล์เปล่าของคุณด้วย ขอบคุณ
Arnaud P

2
ฉันมีเวอร์ชั่นที่ง่ายยิ่งขึ้น: resolve(reader.result.replace(/^.*,/, ''));. เนื่องจากอาการโคม่า,อยู่นอก base64 ตัวอักษรเราจึงสามารถตัดสิ่งที่เกิดขึ้นจนถึงและรวมถึงอาการโคม่า stackoverflow.com/a/13195218/1935128
Johnride

ตกลงขอบคุณสำหรับหัวขึ้นแม้ว่าตาม regex ฉันเขียนที่นี่ (ฉันต้องทดลองอีกครั้งเพื่อให้แน่ใจ) อาจจะมีเพียงdata:ไม่มีเครื่องหมายจุลภาคดังนั้นฉันจะเก็บส่วนแรกที่เป็น ฉันได้อัพเดตคำตอบแล้ว
Arnaud P

1
@ArnaudP ข้อผิดพลาด Typescript: คุณสมบัติ 'replace' ไม่มีอยู่ในประเภท 'string | ArrayBuffer'
Romel Gomez

12

ฟังก์ชัน JavaScript btoa ()สามารถใช้ในการแปลงข้อมูลเป็นสตริงที่เข้ารหัส base64


6
btoa ใช้ได้กับสตริงเท่านั้น จะใช้งานกับไฟล์ได้อย่างไร?
Vassily

10
คุณจะต้องอ่านไฟล์ก่อนแล้วจึงส่งไปยังฟังก์ชั่นนี้ .. บางอย่างเช่นjsfiddle.net/eliseosoto/JHQnk
Pranav Maniar

1
@PranavManiar ซอของคุณไม่ทำงานอีกต่อไป คุณสามารถอัพเดทลิงค์ได้ไหม
Dan

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]);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.