1

I want to use fileSaver.js to click a button and save a binary blob (type: "application/octet-stream"). But i don´t know how to save the blob the way i need it to be.

The final file (example.mod) needs to have the following sequence:

  • 8 (the number of bytes for the next peace of information, integer number)
  • <POINTS> (a tag name with 8 characters)
  • 3 (the number of points)
  • [A,10.5,10,10] (a point: an array with a letter and 3 floating numbers)
  • [B,20,10,0.7] (a point: an array with a letter and 3 floating numbers)
  • [C,10,20.3,10] (a point: an array with a letter and 3 floating numbers)
  • 9 (the number of bytes for the next peace of information, integer number)
  • </POINTS> (a tag name with 9 characters)

I´ve found some examples saving "text/plain" or "image/png", but nothing that I could figure out how to apply in my case.

I've made this CodePen showing what I´m trying to do, but the resulting file is not what expected! it returns a file like that (all the information is visible as if was a text file):

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

...but what I would like to get is the file writen in Bytes, something like this (when looked at in a text-editor):

enter image description here

...or when read it as an ArrayBuffer I should get something like this result:

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: If you know how to get those results without using filesaver.js, that would work for me as well.

Any help will be most appreciated!

Thank you.

1
  • I am trying to prepare the data with Arraybuffer e typed arrays before creating the blob, but with no success so far. Really lost here! :( Commented Feb 1, 2021 at 0:53

1 Answer 1

1

Solved:

After digging for a while found in different questions the bits and peaces i needed to put together a solution (not sure if is the best practice, but is working!)

First I had to treat every kind of input (string, number(positive integer), number(signed floating real) in differnet ways to match the format I need in the file.

*1: from here got the StingToArrayBuffer solution

//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: From that answer got the numberToArrayBuffer solution, modified to my needs!

//.............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: from this one, figure how to save the point coordinates

//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: preparing the data sequence and concatenating the 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: Codepen from David

*6: Correction on the blob syntax

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

Here is the Codepen with the Solution. Thank You.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.