【问题标题】:Filesaver.js: how to write a blob containing binary data?Filesaver.js:如何编写包含二进制数据的 blob?
【发布时间】:2021-05-04 09:14:09
【问题描述】:

我想使用 fileSaver.js 单击按钮并保存 二进制 blob(类型:“application/octet-stream”)。 但我不知道如何按照我需要的方式保存 blob。

最终文件(example.mod)需要有以下顺序:

  • 8(下次和平信息的字节数,整数)
  • <POINTS>(8个字符的标签名)
  • 3(点数)
  • [A,10.5,10,10](一个点:一个包含一个字母和3个浮点数的数组)
  • [B,20,10,0.7](一个点:一个包含一个字母和3个浮点数的数组)
  • [C,10,20.3,10](一个点:一个包含一个字母和3个浮点数的数组)
  • 9(下次和平信息的字节数,整数)
  • </POINTS>(9个字符的标签名)

我找到了一些保存“text/plain”或“image/png”的示例,但我无法弄清楚如何在我的情况下应用。

我已经制作了这个CodePen,显示了我正在尝试做的事情,但生成的文件不是预期的! 它返回一个类似的文件(所有信息都像文本文件一样可见):

8<POINTS>3A,10.5,10,10B,20,10,0.7C,10,20.3,109</POINTS>

...但我想得到的是用字节写的文件,像这样(在文本编辑器中查看时):

...或者当它作为 ArrayBuffer 读取时,我应该得到类似这样的结果:

Int8Array(119)[
    0: 0
    1: 0
    2: 0
    3: 8
    4: 60
    5: 80
    6: 79
    7: 73
    8: 78
    9: 84
    10: 83
    11: 62
    12: 3
    13: 0
    14: 0
    15: 0
    16: 2
    17: 0
    18: 0
    19: 0
    20: 1
    21: 65
    22: 0
    23: 0
    24: 0
    25: 0
    26: 0
    27: 0
    28: 37
    29: 64
    30: 0
    31: 0
    32: 0
    33: 0
    34: 0
    35: 0
    36: 36
    37: 64
    38: 0
    39: 0
    40: 0
    41: 0
    42: 0
    43: 0
    44: 36
    45: 64
    46: 2
    47: 0
    48: 0
    49: 0
    50: 1
    51: 66
    52: 0
    53: 0
    54: 0
    55: 0
    56: 0
    57: 0
    ​​58: 52
    ​​59: 64
    ​​60: 0
    ​​61: 0
    ​​62: 0
    ​​63: 0
    ​​64: 0
    65: 0
    66: 36
    ​​67: 64
    ​​68: 102
    ​​69: 102
    ​​70: 102
    ​​71: 102
    72: 102
    ​​73: 102
    ​​74: -26
    ​​75: 63
    76: 2
    77: 0
    ​​78: 0
    79: 0
    ​​80: 1
    ​​81: 67
    ​​82: 0
    ​​83: 0
    ​​84: 0
    ​​85: 0
    ​​86: 0
    87: 0
    ​​88: 36
    ​​89: 64
    ​​90: -51
    ​​91: -52
    ​​92: -52
    ​​93: -52
    ​​94: -52
    ​​95: 76
    96: 52
    ​​97: 64
    98: 0
    ​​99: 0
    100: 0
    ​​101: 0
    ​​102: 0
    ​​103: 0
    ​​104: 36
    105: 64
    ​​106: 0
    107: 0
    108: 0
    ​​109: 9
    ​​110: 60
    ​​111: 47
    ​​112: 80
    ​​113: 79
    ​​114: 73
    ​​115: 78
    ​​116: 84
    ​​117: 83
    ​​118: 62
]

PS:如果您知道如何在不使用 filesaver.js 的情况下获得这些结果,那也适用于我。

任何帮助将不胜感激!

谢谢。

【问题讨论】:

  • 我正在尝试在创建 blob 之前使用 Arraybuffer e 类型的数组准备数据,但到目前为止没有成功。真的迷路了! :(

标签: javascript save blob filesaver.js


【解决方案1】:

已解决:

在挖掘了一段时间后,在不同的问题中发现了我需要整理的解决方案(不确定是否是最佳做法,但正在工作!)

首先,我必须以不同的方式处理每种输入(字符串、数字(正整数)、数字(有符号浮点实数))以匹配我在文件中需要的格式。

*1: 从这里得到了 StingToArrayBuffer 解决方案

//string to ArrayBuffer
function str2ab(str) {
  var buf = new ArrayBuffer(str.length); // 2 bytes for each char
  var bufView = new Uint8Array(buf);
  for (var i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  var result = new Uint8Array(bufView.buffer);
  return result;
}

*2: 从那个答案中得到了 numberToArrayBuffer 解决方案,根据我的需要进行了修改!

//.............number to ArratBuffer //*2
//integer To ArrayBuffer - 4 bits
function int2ArrBuf(value) {
  const view = new DataView(new ArrayBuffer(4))
  for (var index = 3; index >= 0; --index) {
    view.setUint8(index, value % 256)
    value = value >> 8;
  }
  var int = new Uint8Array(view.buffer);
  return int
}

//Reverse order
function Xint2ArrBuf(value) {
  const view = new DataView(new ArrayBuffer(4))
  for (var index = 0; index <= 3; ++index) {
    view.setUint8(index, value % 256)
    value = value >> 8;
  }
  var int = new Uint8Array(view.buffer);
  return int
}
//......................

//one bit long integer
function strsize(value) {
  const view = new DataView(new ArrayBuffer(1))
  
    view.setUint8(0, value % 256)
    value = value >> 8;
 
  var result= new Uint8Array(view.buffer);
  return result
}

*3:从这个,图怎么保存点坐标

//point To ArrayBuffer - 3x 8 bits
function Pt2ArrBuf(x,y,z){
  var float32 = new Float32Array(3);
  float32[0] = x;
  float32[1] = y;
  float32[2] = z;

  var f = new Float64Array(float32);
  var pt = new Int8Array(f.buffer);  
  
  return pt;
}

*4:准备数据序列并连接TypedArrays

//here I write the file the way i Need it to be...

const binaryData = [
    int2ArrBuf(9),
    strsize(8),
    str2ab('<POINTS>'),
    int2ArrBuf(3),
    Xint2ArrBuf(2),
    strsize(1),
    str2ab('A'),
    Pt2ArrBuf(10.5,10,10),
    Xint2ArrBuf(2),
    strsize(1),
    str2ab('B'),
    Pt2ArrBuf(-20,10,0.7),
    int2ArrBuf(10),
    strsize(9),
    str2ab('</POINTS>') 
  ];

//here I join the many TypedArrays into one...
const mergedInt8Array = new Int8Array(binaryData.map(typedArray => [...new Int8Array(typedArray.buffer)]).flat());
console.log(mergedInt8Array);

*5:David 的 Codepen

*6:对blob语法的更正

//*5:direct download via FileSaver.js
var SaveButton = document.getElementById('save');
SaveButton.addEventListener('click', function () {
  var filename = document.getElementById("name").value;
  filename += '.txt';
  var blob = new Blob([mergedInt8Array], { type: "application/octet-stream"}); //*6
  saveAs(blob, filename);
});

这是带有解决方案的Codepen。谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 2013-06-09
    • 2011-12-08
    • 1970-01-01
    相关资源
    最近更新 更多