我正在尝试从文件系统读取二进制文件,然后使用JavaScript对base64进行编码。我正在使用FileReader API读取数据,而base64编码器找到了here

我所拥有的代码似乎接近工作,问题在于生成的base64数据是错误的。到目前为止,这是我得到的:

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

这是我正在测试的文件(它是一个100x100的蓝色正方形):

根据online base64 decoder/encoder,此文件应编码为:



...但是我从JavaScript中得到的却是:



如果我不得不冒险猜测,我会说这个问题与二进制数据中不可打印的字符有关(如果我对纯文本文档进行编码,则可以很好地工作)。但是,解决此问题的最佳方法是什么?

编辑

看来这可能是base64库本身的问题(如果不是,则可能是Uint8Array如何解包到库调用的字符串中)。如果我改用浏览器的btoa()函数,并直接将Uint8Array binaryText传递给它,则可以正常工作。不幸的是,该功能并非在所有浏览器中都存在。

最佳答案

和谷歌一起营救。我发现以下代码,将输入数据作为“字节”的简单数组(0到255之间的数字,包括0和255;如果直接将Uint8Array传递给它,也可以正常工作),并将其添加到我正在使用的库中:

//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' +
    '0123456789';

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

包含上述功能的库的完整代码为available here,但其未经修改的形式似乎依赖于许多其他库。上面略微修改过的版本适用于只需要快速解决此问题的任何人。

关于javascript - 读取并以base64编码二进制文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15149997/

10-12 15:36
查看更多