Filesaver.js: 如何写入包含二进制数据的 blob?
Filesaver.js: how to write a blob containing binary data?
我想使用 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 来展示我正在尝试做的事情,但是生成的文件不是预期的!
它 returns 一个这样的文件(所有信息都像文本文件一样可见):
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 的情况下获得这些结果,那对我也有用。
任何帮助将不胜感激!
谢谢。
已解决:
在挖掘了一段时间后,在不同的问题中发现了我需要整理出一个解决方案的点点滴滴(不确定这是否是最佳实践,但正在发挥作用!)
首先,我必须以不同的方式处理各种输入(字符串、数字(正整数)、数字(带符号的浮点实数)以匹配我在文件中需要的格式。
*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
}
从这个开始,图解如何保存点坐标
//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
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 的解决方案。谢谢。
我想使用 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 来展示我正在尝试做的事情,但是生成的文件不是预期的! 它 returns 一个这样的文件(所有信息都像文本文件一样可见):
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 的情况下获得这些结果,那对我也有用。
任何帮助将不胜感激!
谢谢。
已解决:
在挖掘了一段时间后,在不同的问题中发现了我需要整理出一个解决方案的点点滴滴(不确定这是否是最佳实践,但正在发挥作用!)
首先,我必须以不同的方式处理各种输入(字符串、数字(正整数)、数字(带符号的浮点实数)以匹配我在文件中需要的格式。
*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
}
//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
//*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 的解决方案。谢谢。