Mã hóa và giải mã Base64 trong Javascript phía máy khách


Câu trả lời:


214

Một số trình duyệt như Firefox, Chrome, Safari, Opera và IE10 + có thể xử lý Base64 nguyên bản. Hãy xem câu hỏi Stackoverflow này . Đó là sử dụng btoa()atob()chức năng .

Đối với JavaScript phía máy chủ (Nút), bạn có thể sử dụng Buffers để giải mã.

Nếu bạn đang tìm giải pháp cho nhiều trình duyệt, có những thư viện hiện có như CryptoJS hoặc mã như:

http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

Với cái sau, bạn cần kiểm tra kỹ lưỡng chức năng để tương thích trình duyệt chéo. Và lỗi đã được báo cáo .


1
Tôi đã sử dụng phương pháp này để mã hóa một SVG trong base64 với lược đồ Date URI. Điều ngạc nhiên: chức năng này mã hóa mọi ký tự, vì vậy tôi nhận được XML không đúng định dạng này ở mục tiêu:% 3C% 3Fxml% 20version% 3D% 271.0% 27% 20% 3F% 3E% 3Csvg% 20xmlns% 3D% 27http% ...
Dereckson

21
Node.js có thể thực hiện Base64 nguyên bản: new Buffer('Hello, world!').toString('base64'); new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii'); (nguồn)
nyuszika7h

Và nếu tôi muốn làm nó an toàn URL?
anddero

1
trong nút 5+, sử dụng Buffer.from, new Buffer(string)không được dùng nữa. Buffer.from(jwt.split('.')[1], 'base64').toString()
Ray Foss

63

Trong các trình duyệt dựa trên Gecko / WebKit (Firefox, Chrome và Safari) và Opera, bạn có thể sử dụng btoa ()atob () .

Câu trả lời gốc: Làm thế nào bạn có thể mã hóa một chuỗi thành Base64 trong JavaScript?


Đây là một cứu tinh. Tôi đã sử dụng một vài cách triển khai khác nhau để giải mã các chuỗi mã hóa base64 rất lớn và kết quả luôn sai. atob () hoạt động tuyệt vời!
b2238488

15
Nitlog nhỏ: Opera không dựa trên Gecko hoặc Webkit, nó sử dụng công cụ kết xuất của riêng mình được gọi là Presto.
Peter Olson

Wow, cảm ơn vì điều này. Không biết có một bộ mã hóa base64 gốc trong các trình duyệt này!
Rob Porter

5
@PeterOlson Không còn nữa :)
Mustafa

1
Tôi nhận ra đây là một bài viết cũ, nhưng về mối quan tâm của @ b2238488, bạn có thể tách chuỗi base64 để mỗi độ dài của mã thông báo là bội số của 4 và giải mã chúng một cách riêng biệt. Kết quả sẽ giống như giải mã toàn bộ chuỗi cùng một lúc.
nyuszika7h

56

Internet Explorer 10+

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = btoa(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = atob(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

Qua trình duyệt

Các thư viện / mô-đun mã hóa và giải mã Javascript UTF-8 và Base64 được viết lại và mô đun hóa cho AMD, CommonJS, Nodejs và trình duyệt. Tương thích trình duyệt chéo.


với Node.js

Đây là cách bạn mã hóa văn bản bình thường thành base64 trong Node.js:

//Buffer() requires a number, array or string as the first parameter, and an optional encoding type as the second parameter. 
// Default is utf8, possible encoding types are ascii, utf8, ucs2, base64, binary, and hex
var b = new Buffer('JavaScript');
// If we don't use toString(), JavaScript assumes we want to convert the object to utf8.
// We can make it convert to other formats by passing the encoding type to toString().
var s = b.toString('base64');

Và đây là cách bạn giải mã các chuỗi được mã hóa base64:

var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();

với Dojo.js

Để mã hóa một mảng byte bằng cách sử dụng dojox.encoding.base64:

var str = dojox.encoding.base64.encode(myByteArray);

Để giải mã chuỗi mã hóa base64:

var bytes = dojox.encoding.base64.decode(str)

Bower cài đặt angular-base64

<script src="bower_components/angular-base64/angular-base64.js"></script>

angular
    .module('myApp', ['base64'])
    .controller('myController', [

    '$base64', '$scope', 
    function($base64, $scope) {
    
        $scope.encoded = $base64.encode('a string');
        $scope.decoded = $base64.decode('YSBzdHJpbmc=');
}]);

Nhưng bằng cách nào?

Nếu bạn muốn tìm hiểu thêm về cách mã hóa Base64 nói chung và nói riêng về JavaScript, tôi muốn giới thiệu bài viết này: Khoa học máy tính trong JavaScript: Mã hóa Base64


1
FYI: Phiên bản trình duyệt chéo có một số rò rỉ khó chịu c2và có khả năng c1c3do đó, nó sẽ không hoạt động "use strict"như được định nghĩa ở trên.
Campbeln

41

Đây là một phiên bản thắt chặt của bài Sniper. Nó giả định chuỗi base64 được hình thành tốt mà không có lợi nhuận vận chuyển. Phiên bản này giúp loại bỏ một vài vòng lặp, thêm bản &0xffsửa lỗi từ Yaroslav, loại bỏ các null null, cộng với một chút mã golf.

decodeBase64 = function(s) {
    var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;
    var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    for(i=0;i<64;i++){e[A.charAt(i)]=i;}
    for(x=0;x<L;x++){
        c=e[s.charAt(x)];b=(b<<6)+c;l+=6;
        while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}
    }
    return r;
};

5
Thậm chí ít byte hơn; DdecodeBase64=function(f){var g={},b=65,d=0,a,c=0,h,e="",k=String.fromCharCode,l=f.length;for(a="";91>b;)a+=k(b++);a+=a.toLowerCase()+"0123456789+/";for(b=0;64>b;b++)g[a.charAt(b)]=b;for(a=0;a<l;a++)for(b=g[f.charAt(a)],d=(d<<6)+b,c+=6;8<=c;)((h=d>>>(c-=8)&255)||a<l-2)&&(e+=k(h));return e};
Der Hochstapler

Vâng nhưng chỉ hoạt động với ASCII. Các nhân vật Cyr được đọc sai ví dụ.
Martin Kovachev

@MartinKovachev bạn có thể đăng một bình luận mới với văn bản ví dụ với ký tự Cyr và mã hóa base64 tương ứng không? Có lẽ chúng ta có thể sửa mã để chứa.
broc.seib

Ở đây: một cái gì đó như thế: фраза тестова
Martin Kovachev

2
@OliverSalzburg Thậm chí ít tạo bảng mã :):var g={},k=String.fromCharCode,i;for(i=0;i<64;)g[k(i>61?(i&1)*4|43:i+[65,71,-4][i/26&3])]=i++;
Mike

34

Chức năng giải mã JavaScript Base64 ngắn và nhanh mà không cần Failsafe:

function decode_base64 (s)
{
    var e = {}, i, k, v = [], r = '', w = String.fromCharCode;
    var n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];

    for (z in n)
    {
        for (i = n[z][0]; i < n[z][1]; i++)
        {
            v.push(w(i));
        }
    }
    for (i = 0; i < 64; i++)
    {
        e[v[i]] = i;
    }

    for (i = 0; i < s.length; i+=72)
    {
        var b = 0, c, x, l = 0, o = s.substring(i, i+72);
        for (x = 0; x < o.length; x++)
        {
            c = e[o.charAt(x)];
            b = (b << 6) + c;
            l += 6;
            while (l >= 8)
            {
                r += w((b >>> (l -= 8)) % 256);
            }
         }
    }
    return r;
}

6
Opera 11.62 dường như có vấn đề với phần '% 256'. Thay thế nó bằng '& 0xff' làm cho nó hoạt động.
Yaroslav Stavnichiy

Mã javascript điểm cuối ảo Tyk dường như có vấn đề với phần '\ x00'. Thay thế nó bằng r = r.replace (/ \ x00 / g, '') làm cho nó hoạt động
Panupong Kongarn


11

Các php.js dự án có triển khai JavaScript của nhiều chức năng của PHP. base64_encodebase64_decodeđược bao gồm.


php.js là hóa thân của mọi tội lỗi và thuộc về tầng lớp của chính nó trong địa ngục. Tránh nó như bệnh dịch hạch. (Thông tin thêm: softwareengineering.stackexchange.com/questions/126671/
triệt

Tôi không thấy nhiều sự ủng hộ khẳng định chăn đó trong liên kết đó, @Coreus. Được sử dụng một cách thận trọng, hoặc như một điểm khởi đầu, đó là một cách hoàn toàn có thể chấp nhận được để tìm ra logic tương đương trong JS cho một cái gì đó mà bạn có thể đã biết cách làm trong PHP.
ceejayoz

9

Có ai nói mã golf? =)

Sau đây là nỗ lực cải thiện điểm chấp của tôi trong khi bắt kịp thời đại. Cung cấp cho sự thuận tiện của bạn.

function decode_base64(s) {
  var b=l=0, r='',
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  s.split('').forEach(function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  });
  return r;
}

Những gì tôi thực sự sau đó là một triển khai không đồng bộ và thật ngạc nhiên, nó hóa ra forEachtrái ngược với JQuery$([]).each triển khai phương thức là rất đồng bộ.

Nếu bạn cũng có những khái niệm điên rồ như vậy, window.setTimeoutthì độ trễ 0 sẽ chạy giải mã base64 không đồng bộ và thực hiện chức năng gọi lại với kết quả khi hoàn tất.

function decode_base64_async(s, cb) {
  setTimeout(function () { cb(decode_base64(s)); }, 0);
}

@Toothbrush đề xuất "lập chỉ mục một chuỗi như một mảng" và loại bỏ split. Thói quen này có vẻ rất kỳ quặc và không chắc nó sẽ tương thích như thế nào, nhưng nó đã đánh trúng một birdie khác vì vậy hãy cho phép nó.

function decode_base64(s) {
  var b=l=0, r='',
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  [].forEach.call(s, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  });
  return r;
}

Trong khi cố gắng tìm thêm thông tin về chuỗi JavaScript dưới dạng mảng, tôi đã tình cờ tìm thấy mẹo chuyên nghiệp này bằng cách sử dụng biểu thức chính quy /./gđể bước qua chuỗi. Điều này làm giảm kích thước mã hơn nữa bằng cách thay thế chuỗi tại chỗ và loại bỏ nhu cầu giữ biến trả về.

function decode_base64(s) {
  var b=l=0,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  return s.replace(/./g, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    return l<8?'':String.fromCharCode((b>>>(l-=8))&0xff);
  });
}

Tuy nhiên, nếu bạn đang tìm kiếm một cái gì đó truyền thống hơn một chút có lẽ sau đây là nhiều hơn với sở thích của bạn.

function decode_base64(s) {
  var b=l=0, r='', s=s.split(''), i,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  for (i in s) {
    b=(b<<6)+m.indexOf(s[i]); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  }
  return r;
}

Tôi không có vấn đề null cuối cùng vì vậy vấn đề này đã được gỡ bỏ để duy trì dưới mức trung bình nhưng nó có thể dễ dàng được giải quyết bằng một trim()hoặc mộttrimRight() nếu bạn muốn, nếu điều này gây ra vấn đề cho bạn.

I E.

return r.trimRight();

Ghi chú:

Kết quả là một chuỗi byte ascii, nếu bạn cần unicode thì dễ nhất là escapechuỗi byte mà sau đó có thể được giải mã decodeURIComponentđể tạo ra chuỗi unicode.

function decode_base64_usc(s) {      
  return decodeURIComponent(escape(decode_base64(s)));
}

escapeđang bị phản đối, chúng tôi có thể thay đổi chức năng của mình để hỗ trợ unicode trực tiếp mà không cần escapehoặc String.fromCharCodechúng tôi có thể tạo ra một %chuỗi thoát sẵn sàng để giải mã URI.

function decode_base64(s) {
  var b=l=0,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  return decodeURIComponent(s.replace(/./g, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
  }));
}

Xin chào!


3
Bạn không cần splitchuỗi, vì bạn có thể lập chỉ mục chuỗi JavaScript như một mảng. s.split('').forEach(function ...có thể được thay thế bởi [].forEach.call(s, function .... Nó sẽ nhanh hơn rất nhiều, do nó không phải phân tách chuỗi.
Bàn chải đánh răng

Cái "truyền thống hơn" đã bị phá vỡ hoàn toàn đối với tôi - tạo ra một mớ hỗn độn bị cắt xén với dấu vết của văn bản gốc được rắc khắp nơi. Trên Chrome.
Steve Bennett

@Steve Bennett Tôi đã thử nghiệm tất cả các biến thể trong chrome ... nó hoạt động. Bạn có thể cung cấp một chuỗi ví dụ base64 không thành công?
nickl-

Ba năm sau? Hà. Tôi thậm chí không nhớ những gì tôi cần cái này cho.
Steve Bennett

6

Tôi đã thử các thói quen Javascript tại phpjs.org và chúng đã hoạt động tốt.

Lần đầu tiên tôi thử các thói quen được đề xuất trong câu trả lời được chọn bởi Ranhiru Cooray - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

Tôi thấy rằng họ đã không làm việc trong mọi hoàn cảnh. Tôi đã viết lên một trường hợp thử nghiệm trong đó những thói quen này thất bại và đăng chúng lên GitHub tại:

https://github.com/scottcarter/base64_javascript_test_data.git

Tôi cũng đã đăng một bình luận lên bài đăng trên blog tại ntt.cc để cảnh báo cho tác giả (đang chờ kiểm duyệt - bài viết đã cũ nên không chắc chắn nếu bình luận sẽ được đăng).


1

Tôi muốn sử dụng các phương thức mã hóa / giải mã bas64 từ CryptoJS , thư viện phổ biến nhất cho các thuật toán mã hóa tiêu chuẩn và an toàn được triển khai trong JavaScript bằng cách sử dụng các mẫu và thực tiễn tốt nhất.


1

Trong Node.js chúng ta có thể làm điều đó theo cách đơn giản

var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');

console.log(base64_decode); // "Hello World"

0

Đối với các khung công tác JavaScripts không có atobphương thức và trong trường hợp bạn không muốn nhập các thư viện bên ngoài, đây là hàm ngắn thực hiện điều đó.

Nó sẽ nhận được một chuỗi chứa giá trị được mã hóa Base64 và sẽ trả về một mảng byte được giải mã (trong đó mảng byte được biểu diễn dưới dạng mảng các số trong đó mỗi số là một số nguyên nằm trong khoảng từ 0 đến 255).

function fromBase64String(str) {
    var alpha = 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var value = [];
    var index = 0;
    var destIndex  = 0;
    var padding = false;
    while (true) {

        var first  = getNextChr(str, index, padding, alpha);
        var second = getNextChr(str, first .nextIndex, first .padding, alpha);
        var third  = getNextChr(str, second.nextIndex, second.padding, alpha);
        var fourth = getNextChr(str, third .nextIndex, third .padding, alpha);

        index = fourth.nextIndex;
        padding = fourth.padding;

        // ffffffss sssstttt ttffffff
        var base64_first  = first.code  == null ? 0 : first.code;
        var base64_second = second.code == null ? 0 : second.code;
        var base64_third  = third.code  == null ? 0 : third.code;
        var base64_fourth = fourth.code == null ? 0 : fourth.code;

        var a = (( base64_first << 2) & 0xFC ) | ((base64_second>>4) & 0x03);
        var b = (( base64_second<< 4) & 0xF0 ) | ((base64_third >>2) & 0x0F);
        var c = (( base64_third << 6) & 0xC0 ) | ((base64_fourth>>0) & 0x3F);

        value [destIndex++] = a;
        if (!third.padding) {
            value [destIndex++] = b;
        } else {
            break;
        }
        if (!fourth.padding) {
            value [destIndex++] = c;
        } else {
            break;
        }
        if (index >= str.length) {
            break;
        }
    }
    return value;
}

function getNextChr(str, index, equalSignReceived, alpha) {
    var chr = null;
    var code = 0;
    var padding = equalSignReceived;
    while (index < str.length) {
        chr = str.charAt(index);
        if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
            index++;
            continue;
        }
        if (chr == "=") {
            padding = true;
        } else {
            if (equalSignReceived) {
                throw new Error("Invalid Base64 Endcoding character \"" 
                    + chr + "\" with code " + str.charCodeAt(index) 
                    + " on position " + index 
                    + " received afer an equal sign (=) padding "
                    + "character has already been received. "
                    + "The equal sign padding character is the only "
                    + "possible padding character at the end.");
            }
            code = alpha.indexOf(chr);
            if (code == -1) {
                throw new Error("Invalid Base64 Encoding character \"" 
                    + chr + "\" with code " + str.charCodeAt(index) 
                    + " on position " + index + ".");
            }
        }
        break;
    }
    return { character: chr, code: code, padding: padding, nextIndex: ++index};
}

Tài nguyên được sử dụng: RFC-4648 Phần 4

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.