2

我正在尝试使用以下代码从 chrome 扩展中将生成的 zip 文件保存到磁盘:

function sendFile (nm, file) {
  var a = document.createElement('a');
  a.href = window.URL.createObjectURL(file);
  a.download = nm; // file name
  a.style.display = 'none';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}
function downloadZip (nm) {
  window.URL = window.webkitURL || window.URL;
  var content;
  content = zip.generate();
  var file = new Blob ([content], {type:'application/base64'});
  sendFile ("x.b64", file);
  content = zip.generate({base64:false});
  var file = new Blob ([content], {type:'application/binary'});
  sendFile ("x.zip", file);
}

目前,这将我的 zip 的内容保存在两个版本中,第一个是 base64 编码的,当我使用base64 -d生成的 zip 对其进行解码时就可以了。
第二个版本应该只保存原始数据(zip 文件),但是这个原始数据以 utf-8 编码到达我的磁盘上。(每个值 >= 0x80 都以 0xc2 为前缀)。那么如何摆脱这种 utf-8 编码呢?尝试了各种类型字符串,例如application/zip,或完全省略类型信息,它总是以 utf-8 编码到达。我也很好奇如何让浏览器自己存储/转换 base64 数据(第一种情况),以便它们作为解码的二进制数据到达我的磁盘上......我使用的是 Chrome 版本 23.0.1271.95 m

PS:我在浏览器中使用 hexdump-utility 分析的第二个内容:它不包含 utf-8 编码(或者我的 hexdump 调用了一些进行隐式转换的东西)。为了完整起见(抱歉,它只是从 c 转换而来,所以它可能不是那么酷的 js 代码),我将它附加在这里:

function hex (bytes, val) {
  var ret="";
  var tmp="";
  for (var i=0;i<bytes;i++) {
    tmp=val.toString (16);
    if (tmp.length<2)
      tmp="0"+tmp;
    ret=tmp+ret;
    val>>=8;
  }
  return ret;
}
function hexdump (buf, len) {
  var p=0;
  while (p<len) {
    line=hex (2,p);
    var i;
    for (i=0;i<16;i++) {
      if (i==8)
        line +=" ";
      if (p+i<len)
        line+=" "+hex(1,buf.charCodeAt(p+i));
      else
        line+="   ";
    }
    line+=" |";
    for (i=0;i<16;i++) {
      if (p+i<len) {
        var cc=buf.charCodeAt (p+i);
        line+= ((cc>=32)&&(cc<=127)&&(cc!='|')?String.fromCharCode(cc):'.');
      }
    }
    p+=16;
    console.log (line);
  }
}
4

1 回答 1

2

工作草案

如果 element 是 DOMString,请运行以下子步骤:

  • 让 s 是使用 WebIDL [WebIDL] 中的算法将元素转换为 Unicode 字符序列 [Unicode] 的结果。

  • 将 s 编码为 UTF-8 并将结果字节附加到字节。

所以字符串总是被转换为 UTF-8,并且没有任何参数可以影响这一点。这不会影响 base64 字符串,因为它们只包含与每个代码点的单个字节匹配的字符,代码点和字节具有相同的值。幸运的是Blob,它公开了较低级别的接口(直接字节),因此这种限制并不重要。

你可以这样做:

var binaryString = zip.generate({base64: false}), //By glancing over the source I trust the string is in "binary" form
    len = binaryString.length,    //I.E. having only code points 0 - 255 that represent bytes
    bytes = new Uint8Array(len);

for( var i = 0; i < len; ++i ) {
    bytes[i] = binaryString.charCodeAt(i);
}

var file = new Blob([bytes], {type:'application/zip'});
sendFile( "myzip.zip", file );
于 2012-12-10T19:15:57.730 回答