Saving a Uint8Array to a binary file
Asked Answered
B

3

31

I am working on a web app that opens binary files and allows them to be edited.

This process is basically ondrop -> dataTransfer.files[0] -> FileReader -> Uint8Array

Essentially, I want to be able to save the modified file back as a binary file. Ideally as a file download with a specified file name.

There doesn't seem to be any standard method of doing this, and that sucks, because everything up to that point is well supported.

I am currently converting the array to a string using String.fromCharCode(), base64 encoding that, and using a data uri in a hyperlink like data:application/octet-stream;base64,.., along with the download attribute to specify filename.

It seems to work, but it's quite hacky and I think converting the raw bytes to a string might introduce encoding issues depending on the byte values. I don't want the data to become corrupt or break the string.

Barring that, is there a better/proper method for getting an array of bytes as a binary file to the user?

Blowzed answered 17/8, 2014 at 22:39 Comment(0)
V
41

These are utilities that I use to download files cross-browser. The nifty thing about this is that you can actually set the download property of a link to the name you want your filename to be.

FYI the mimeType for binary is application/octet-stream

var downloadBlob, downloadURL;

downloadBlob = function(data, fileName, mimeType) {
  var blob, url;
  blob = new Blob([data], {
    type: mimeType
  });
  url = window.URL.createObjectURL(blob);
  downloadURL(url, fileName);
  setTimeout(function() {
    return window.URL.revokeObjectURL(url);
  }, 1000);
};

downloadURL = function(data, fileName) {
  var a;
  a = document.createElement('a');
  a.href = data;
  a.download = fileName;
  document.body.appendChild(a);
  a.style = 'display: none';
  a.click();
  a.remove();
};

Usage:

downloadBlob(myBinaryBlob, 'some-file.bin', 'application/octet-stream');
Vinitavinn answered 10/11, 2015 at 4:28 Comment(6)
This confuses me, the parameters in downloadURL are different to the parameters used to call it.Durstin
the example uses downloadBlob (the first function) that then calls downloadURL so the args reflect the first function not the 2nd oneVinitavinn
You are calling downloadURL(url, filename, mimeType) from within downloadBlob but the function is downloadURL(data, filename), so unless there is same magic happening that I don't understand, it's not matching. I think it's a case of just removing the mimeType but when first trying to understand it it's still confusing.Durstin
FileSaver.js is a pretty solid library for handling file downloads across multiple browsers. Under the hood it does essentially the same thing as your code but adjusts for different browsers that don't support the method.Blowzed
this is saving a list of integers separated by commas...Unicellular
Awesome! I was able to simply paste this code into the browser console while stopped at a breakpoint and download a UInt8Array to a file in Safari on Mac.Nazarite
C
17

(shorter) ES6 version of the top answer:

const downloadURL = (data, fileName) => {
  const a = document.createElement('a')
  a.href = data
  a.download = fileName
  document.body.appendChild(a)
  a.style.display = 'none'
  a.click()
  a.remove()
}

const downloadBlob = (data, fileName, mimeType) => {

  const blob = new Blob([data], {
    type: mimeType
  })

  const url = window.URL.createObjectURL(blob)

  downloadURL(url, fileName)

  setTimeout(() => window.URL.revokeObjectURL(url), 1000)
}
Caution answered 3/6, 2020 at 15:44 Comment(1)
Even shorter if data is always Blob :) DL=(d,f)=>{let a=document.createElement("a"),u=URL.createObjectURL(d);a.download=f,a.href=u,a.click(),setTimeout(()=>URL.revokeObjectURL(u))}Blowzed
C
0

I found a solution from this link :

"Solution 2: As per Mozilla. Here is an example on how to create a URL to a typed array using a blob. The source of this example is from Mozilla Developer Network's API documentation for Blob."

var blob = new Blob([typedArray.buffer], {type: 'application/octet-stream'});

It works in Edge and Chrome.

Collette answered 25/1, 2024 at 4:30 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.