2013-03-01 28 views
8

Tôi đang cố đọc tệp nhị phân từ hệ thống tệp và sau đó base64 mã hóa tệp đó bằng JavaScript. Tôi đang sử dụng FileReader API để đọc dữ liệu và bộ mã hóa base64 được tìm thấy here.Đọc và mã hóa base64 một tệp nhị phân

Mã tôi có vẻ gần hoạt động, vấn đề là dữ liệu base64 được tạo không đúng. Đây là những gì tôi đã có cho đến nay:

function saveResource() { 
    var file = $(".resourceFile")[0].files[0]; 

    var reader = new FileReader(); 
    reader.onload = function(evt) { 
     var fileData = evt.target.result; 
     var bytes = new Uint8Array(fileData); 
     var binaryText = ''; 

     for (var index = 0; index < bytes.byteLength; index++) { 
      binaryText += String.fromCharCode(bytes[index]); 
     } 

     console.log(Base64.encode(binaryText)); 

    }; 
    reader.readAsArrayBuffer(file); 
}; 

Dưới đây là file tôi đang thử nghiệm với (đó là một 100x100 hình vuông màu xanh):

enter image description here

Theo một online base64 decoder/encoder, tập tin này nên mã hóa để:

/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIy MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4 + Tl5ufo6erx8vP09fb3 + Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3 + Pn6/9oADAMBAAIRAxEAPwDxyiiiv3E8wKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA // Z

... nhưng thay vì những gì tôi nhận được ra khỏi JavaScript là:

w7/DmMO/w6AAEEpGSUYAAQIAAAEAAQAAw7/DmwBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDLDv8ObAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMsO/w4AAEQgAZABkAwEiAAIRAQMRAcO/w4QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoLw7/DhADCtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDLCgcKRwqEII0LCscOBFVLDkcOwJDNicsKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5esKDwoTChcKGwofCiMKJworCksKTwpTClcKWwpfCmMKZwprCosKjwqTCpcKmwqfCqMKpwqrCssKzwrTCtcK2wrfCuMK5wrrDgsODw4TDhcOGw4fDiMOJw4rDksOTw5TDlcOWw5fDmMOZw5rDocOiw6PDpMOlw6bDp8Oow6nDqsOxw7LDs8O0w7XD tsO3w7jDucO6w7/DhAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgvDv8OEAMK1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIywoEIFELCkcKhwrHDgQkjM1LDsBVicsORChYkNMOhJcOxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXrCgsKDwoTChcKGwofCiMKJworCksKTwpTClcKWwpfCmMKZwprCosKjwqTCpcKmwqfCqMKpwqrCssKzwrTCtcK2wrfCuMK5wrrDgsODw4TDhcOGw4fDiMOJw4rDksOTw5TDlcOWw5fDmMOZw5rDosOjw6TDpcOmw6fDqMOpw6rDssOzw7TDtcO2w7fDuMO5w7rDv8OaAAwDAQACEQMRAD8Aw7HDiijCosK/cTzDgMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooAMKiwoooA8O/w5k =

Nếu tôi đã phải nguy hiểm một đoán tôi muốn nói rằng vấn đề này có một cái gì đó để làm với các ký tự không in được trong dữ liệu nhị phân (nếu tôi mã hóa một tài liệu thô, mà hoạt động tốt). Nhưng cách tiếp cận tốt nhất để giải quyết vấn đề là gì?

Sửa

Nó trông như thế này có thể là một vấn đề với các thư viện base64 tự (hoặc nếu không, sau đó với thế Uint8Array là đóng gói thành một chuỗi cho gọi thư viện). Nếu tôi sử dụng chức năng btoa() của trình duyệt thay thế và chuyển trực tiếp số Uint8ArraybinaryText, hoạt động. Quá xấu mà chức năng không tồn tại trong tất cả các trình duyệt.

Trả lời

8

Và Google để giải cứu. Tôi tìm thấy đoạn mã sau, lấy dữ liệu đầu vào như một mảng đồng bằng của "byte" (số từ 0 đến 255, bao gồm; cũng hoạt động tốt nếu Uint8Array được chuyển trực tiếp đến nó) và thêm nó vào thư viện tôi đang sử dụng :

//note: it is assumed that the Base64 object has already been defined 
//License: Apache 2.0 
Base64.byteToCharMap_ = null; 
Base64.charToByteMap_ = null; 
Base64.byteToCharMapWebSafe_ = null; 
Base64.charToByteMapWebSafe_ = null; 
Base64.ENCODED_VALS_BASE = 
    'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 
    'abcdefghijklmnopqrstuvwxyz' + 
    ''; 

/** 
* Our default alphabet. Value 64 (=) is special; it means "nothing." 
* @type {string} 
*/ 
Base64.ENCODED_VALS = Base64.ENCODED_VALS_BASE + '+/='; 
Base64.ENCODED_VALS_WEBSAFE = Base64.ENCODED_VALS_BASE + '-_.'; 

/** 
* Base64-encode an array of bytes. 
* 
* @param {Array.<number>|Uint8Array} input An array of bytes (numbers with 
*  value in [0, 255]) to encode. 
* @param {boolean=} opt_webSafe Boolean indicating we should use the 
*  alternative alphabet. 
* @return {string} The base64 encoded string. 
*/ 
Base64.encodeByteArray = function(input, opt_webSafe) { 
    Base64.init_(); 

    var byteToCharMap = opt_webSafe ? 
         Base64.byteToCharMapWebSafe_ : 
         Base64.byteToCharMap_; 

    var output = []; 

    for (var i = 0; i < input.length; i += 3) { 
    var byte1 = input[i]; 
    var haveByte2 = i + 1 < input.length; 
    var byte2 = haveByte2 ? input[i + 1] : 0; 
    var haveByte3 = i + 2 < input.length; 
    var byte3 = haveByte3 ? input[i + 2] : 0; 

    var outByte1 = byte1 >> 2; 
    var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); 
    var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6); 
    var outByte4 = byte3 & 0x3F; 

    if (!haveByte3) { 
     outByte4 = 64; 

     if (!haveByte2) { 
     outByte3 = 64; 
     } 
    } 

    output.push(byteToCharMap[outByte1], 
       byteToCharMap[outByte2], 
       byteToCharMap[outByte3], 
       byteToCharMap[outByte4]); 
    } 

    return output.join(''); 
}; 

/** 
* Lazy static initialization function. Called before 
* accessing any of the static map variables. 
* @private 
*/ 
Base64.init_ = function() { 
    if (!Base64.byteToCharMap_) { 
    Base64.byteToCharMap_ = {}; 
    Base64.charToByteMap_ = {}; 
    Base64.byteToCharMapWebSafe_ = {}; 
    Base64.charToByteMapWebSafe_ = {}; 

    // We want quick mappings back and forth, so we precompute two maps. 
    for (var i = 0; i < Base64.ENCODED_VALS.length; i++) { 
     Base64.byteToCharMap_[i] = 
      Base64.ENCODED_VALS.charAt(i); 
     Base64.charToByteMap_[Base64.byteToCharMap_[i]] = i; 
     Base64.byteToCharMapWebSafe_[i] = 
      Base64.ENCODED_VALS_WEBSAFE.charAt(i); 
     Base64.charToByteMapWebSafe_[ 
      Base64.byteToCharMapWebSafe_[i]] = i; 
    } 
    } 
}; 

mã đầy đủ cho các thư viện chứa các chức năng trên là available here, nhưng ở dạng không biến đổi của nó dường như phụ thuộc vào một số thư viện khác. Phiên bản hơi bị tấn công ở trên sẽ hoạt động với bất kỳ ai chỉ cần khắc phục nhanh sự cố này.

+0

Đây chính là điều tôi đang tìm kiếm - bất kỳ cơ hội đăng phần giải mã? – Graham

+1

Tôi không có phiên bản phần giải mã của riêng mình vì tôi không cần nó cho mục đích của mình (giải mã được thực hiện phía máy chủ trong trường hợp của tôi). Tuy nhiên, mã nguồn ban đầu của Google có sẵn tại đây: http://docs.closure-library.googlecode.com/git/closure_goog_crypt_base64.js.source.html – aroth

+0

Có, hãy xem điều đó, nhưng nó có các phụ thuộc mà bạn gỡ bỏ trong phần mã hóa của bạn, vì vậy tôi đã hy vọng cho một cái gì đó tương tự, nhưng cảm ơn cho trả lời anyway. – Graham

2

Hãy coi nhị phân là bộ lọc mảng, điều này độc lập với mọi mã hóa ký tự. Hình vuông màu xanh lam (.jpg) của bạn có 361 byte gốc, có nghĩa là octet từ 0..255 (thập phân) và chúng không có ký tự!

Điều đó có nghĩa là: Sử dụng ArrayBuffer để mã hóa điều này thành Base64 với thuật toán base64 nổi tiếng.

Với Perl trở lại nguồn gốc, cho thấy màu xanh vuông như trên:

my $fh = IO::File->new; 
$fh->open("d:/tmp/x.jpg", O_BINARY|O_CREAT|O_RDWR|O_TRUNC) or die $!; 

$fh->print(decode_base64("/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBD 
AQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABkAGQDASIAAhEBAxEB/8QAFQABAQAA 
AAAAAAAAAAAAAAAAAAf/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAUH/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMR 
AD8AjgDcUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//2Q== 
")); 


$fh->close;