Skip to main content

HTTP Downloads

XMLHttpRequest and fetch browser APIs enable binary data transfer between web browser clients and web servers. Since this library works in web browsers, server conversion work can be offloaded to the client! This demo shows a few common scenarios involving browser APIs and popular wrapper libraries.

This demo focuses on downloading files. Other demos cover other HTTP use cases:

Third-Party Hosts and Binary Data

Third-party cloud platforms such as AWS may corrupt raw binary downloads by encoding requests and responses in UTF-8 strings.

For AWS, in the "Binary Media Types" section of the API Gateway console, the "application/vnd.ms-excel" type should be added to ensure that AWS Lambda functions functions can send files to clients.

Downloading Binary Data

Most interesting spreadsheet files are binary data that contain byte sequences that represent invalid UTF-8 characters.

APIs generally provide options to control how downloaded data is interpreted. The arraybuffer response type usually forces the data to be presented as an ArrayBuffer object which can be parsed with the SheetJS read method1.

The following example shows the data flow using fetch to download files:

/* download data into an ArrayBuffer object */
const res = await fetch("https://sheetjs.com/pres.numbers");
const ab = await res.arrayBuffer(); // recover data as ArrayBuffer

/* parse file */
const wb = XLSX.read(ab);

Browser Demos

When the page is accessed, the browser will attempt to download https://sheetjs.com/pres.numbers and read the workbook. The old table will be replaced with a table whose contents match the first worksheet. The table is generated using the SheetJS sheet_to_html method2

Tested Deployments

Each browser demo was tested in the following environments:

BrowserDate
Chrome 1202024-01-30
Safari 17.22024-01-15

XMLHttpRequest

For downloading data, the arraybuffer response type generates an ArrayBuffer that can be viewed as an Uint8Array and fed to the SheetJS read method. For legacy browsers, the option type: "array" should be specified:

/* set up an async GET request */
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.responseType = "arraybuffer";

req.onload = function(e) {
/* parse the data when it is received */
var data = new Uint8Array(req.response);
var workbook = XLSX.read(data, {type:"array"});
/* DO SOMETHING WITH workbook HERE */
};
req.send();
Live Download demo (click to show)

This demo uses XMLHttpRequest to download https://sheetjs.com/pres.numbers and show the data in an HTML table.

Result
Loading...
Live Editor
function SheetJSXHRDL() {
  const [__html, setHTML] = React.useState("");

  /* Fetch and update HTML */
  React.useEffect(() => { (async() => {
    /* Fetch file */
    const req = new XMLHttpRequest();
    req.open("GET", "https://sheetjs.com/pres.numbers", true);
    req.responseType = "arraybuffer";
    req.onload = e => {
      /* Parse file */
      const wb = XLSX.read(new Uint8Array(req.response));
      const ws = wb.Sheets[wb.SheetNames[0]];

      /* Generate HTML */
      setHTML(XLSX.utils.sheet_to_html(ws));
    };
    req.send();
  })(); }, []);

  return ( <div dangerouslySetInnerHTML={{ __html }}/> );
}

fetch

For downloading data, Response#arrayBuffer resolves to an ArrayBuffer that can be converted to Uint8Array and passed to the SheetJS read method:

fetch(url).then(function(res) {
/* get the data as a Blob */
if(!res.ok) throw new Error("fetch failed");
return res.arrayBuffer();
}).then(function(ab) {
/* parse the data when it is received */
var data = new Uint8Array(ab);
var workbook = XLSX.read(data, {type:"array"});

/* DO SOMETHING WITH workbook HERE */
});
Live Download demo (click to show)

This demo uses fetch to download https://sheetjs.com/pres.numbers and show the data in an HTML table.

Result
Loading...
Live Editor
function SheetJSFetchDL() {
  const [__html, setHTML] = React.useState("");

  /* Fetch and update HTML */
  React.useEffect(() => { (async() => {
    /* Fetch file */
    const res = await fetch("https://sheetjs.com/pres.numbers");
    const ab = await res.arrayBuffer();

    /* Parse file */
    const wb = XLSX.read(ab);
    const ws = wb.Sheets[wb.SheetNames[0]];

    /* Generate HTML */
    setHTML(XLSX.utils.sheet_to_html(ws));
  })(); }, []);

  return ( <div dangerouslySetInnerHTML={{ __html }}/> );
}

jQuery

jQuery is a JavaScript library that includes helpers for performing "Ajax" network requests. jQuery.ajax ($.ajax) does not support binary data out of the box3. A custom ajaxTransport can add support.

SheetJS users have reported success with jquery.binarytransport.js4 in IE10.

After including the main jquery.js and jquery.binarytransport.js scripts, $.ajax will support dataType: "binary" and processData: false.

Live Download Demo

In a GET request, the default behavior is to return a Blob object. Passing responseType: "arraybuffer" returns a proper ArrayBuffer object in IE10:

$.ajax({
type: "GET", url: "https://sheetjs.com/pres.numbers",

/* suppress jQuery post-processing */
processData: false,

/* use the binary transport */
dataType: "binary",

/* pass an ArrayBuffer in the callback */
responseType: "arraybuffer",

success: function (ab) {
/* at this point, ab is an ArrayBuffer */
var wb = XLSX.read(ab);

/* do something with workbook here */
var ws = wb.Sheets[wb.SheetNames[0]];
var html = XLSX.utils.sheet_to_html(ws);
$("#out").html(html);
}
});

Wrapper Libraries

Before fetch shipped with browsers, there were various wrapper libraries to simplify XMLHttpRequest. Due to limitations with fetch, these libraries are still relevant.

axios

axios presents a Promise based interface. Setting responseType to arraybuffer ensures the return type is an ArrayBuffer. The data property of the result can be passed to the SheetJS read method:

async function workbook_dl_axios(url) {
const res = await axios(url, {responseType:'arraybuffer'});
const workbook = XLSX.read(res.data);
return workbook;
}
Live Download demo (click to show)

This demo uses axios to download https://sheetjs.com/pres.numbers and show the data in an HTML table.

If the live demo shows a message

ReferenceError: axios is not defined

please refresh the page. This is a known bug in the documentation generator.

Result
Loading...
Live Editor
function SheetJSAxiosDL() {
  const [__html, setHTML] = React.useState("");

  /* Fetch and update HTML */
  React.useEffect(() => { (async() => {
    if(typeof axios != "function") return setHTML("ReferenceError: axios is not defined");
    /* Fetch file */
    const res = await axios("https://sheetjs.com/pres.numbers", {responseType: "arraybuffer"});

    /* Parse file */
    const wb = XLSX.read(res.data);
    const ws = wb.Sheets[wb.SheetNames[0]];

    /* Generate HTML */
    setHTML(XLSX.utils.sheet_to_html(ws));
  })(); }, []);

  return ( <div dangerouslySetInnerHTML={{ __html }}/> );
}

superagent

superagent is a network request library with a "Fluent Interface". Calling the responseType method with "arraybuffer" will ensure the final response object is an ArrayBuffer:

/* set up an async GET request with superagent */
superagent
.get(url)
.responseType('arraybuffer')
.end(function(err, res) {
/* parse the data when it is received */
var data = new Uint8Array(res.body);
var workbook = XLSX.read(data, {type:"array"});

/* DO SOMETHING WITH workbook HERE */
});
Live Download demo (click to show)

This demo uses superagent to download https://sheetjs.com/pres.numbers and show the data in an HTML table.

If the live demo shows a message

ReferenceError: superagent is not defined

please refresh the page. This is a known bug in the documentation generator.

Result
Loading...
Live Editor
function SheetJSSuperAgentDL() {
  const [__html, setHTML] = React.useState("");

  /* Fetch and update HTML */
  React.useEffect(() => { (async() => {
    if(typeof superagent == "undefined" || typeof superagent.get != "function")
      return setHTML("ReferenceError: superagent is not defined");
    /* Fetch file */
    superagent
      .get("https://sheetjs.com/pres.numbers")
      .responseType("arraybuffer")
      .end((err, res) => {
        /* Parse file */
        const wb = XLSX.read(res.body);
        const ws = wb.Sheets[wb.SheetNames[0]];

        /* Generate HTML */
        setHTML(XLSX.utils.sheet_to_html(ws));
      });
  })(); }, []);

  return ( <div dangerouslySetInnerHTML={{ __html }}/> );
}

NodeJS Demos

These examples show how to download data in NodeJS.

HTTPS GET

The https module provides a low-level get method for HTTPS GET requests:

SheetJSHTTPSGet.js
var https = require("https"), XLSX = require("xlsx");

https.get('https://sheetjs.com/pres.numbers', function(res) {
var bufs = [];
res.on('data', function(chunk) { bufs.push(chunk); });
res.on('end', function() {
var buf = Buffer.concat(bufs);
var wb = XLSX.read(buf);
/* print the first worksheet to console */
var ws = wb.Sheets[wb.SheetNames[0]];
console.log(XLSX.utils.sheet_to_csv(ws));
});
});
Complete Example (click to show)
Tested Environments

This demo was last tested on 2024 January 15 against NodeJS 20.11.0

  1. Install the NodeJS module
npm i --save https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz
  1. Copy the SheetJSHTTPSGet.js code snippet to a file SheetJSHTTPSGet.js

  2. Run the script:

node SheetJSHTTPSGet.js

If successful, the script will print CSV contents of the test file.

fetch

Experimental support for fetch was introduced in NodeJS 16.15.0. It will be considered stable in NodeJS LTS version 22.

The fetch implementation has the same return types as the browser version:

async function parse_from_url(url) {
const res = await fetch(url);
if(!res.ok) throw new Error("fetch failed");
const ab = await res.arrayBuffer();
const workbook = XLSX.read(ab);
return workbook;
}
Complete Example (click to show)
Tested Environments

This demo was last tested on 2024 January 15 against NodeJS 20.11.0

  1. Install the NodeJS module
npm i --save https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz
  1. Save the following to SheetJSFetch.js:
SheetJSFetch.js
var XLSX = require("xlsx");

async function parse_from_url(url) {
const res = await fetch(url);
if(!res.ok) throw new Error("fetch failed");
const ab = await res.arrayBuffer();
const workbook = XLSX.read(ab);
return workbook;
}

(async() => {
const wb = await parse_from_url('https://sheetjs.com/pres.numbers');
/* print the first worksheet to console */
var ws = wb.Sheets[wb.SheetNames[0]];
console.log(XLSX.utils.sheet_to_csv(ws));
})();
  1. Run the script:
node SheetJSFetch.js

If successful, the script will print CSV contents of the test file.

Wrapper Libraries

The latest releases of NodeJS support fetch natively. Before fetch support was added to the platform, third party modules wrapped the native APIs.

request

request has been deprecated and should only be used in legacy deployments.

Setting the option encoding: null passes raw buffers:

SheetJSRequest.js
var XLSX = require('xlsx'), request = require('request');
var url = 'https://sheetjs.com/pres.numbers';

/* call `request` with the option `encoding: null` */
request(url, {encoding: null}, function(err, res, data) {
if(err || res.statusCode !== 200) return;

/* if the request was successful, parse the data */
var wb = XLSX.read(data);

/* print the first worksheet to console */
var ws = wb.Sheets[wb.SheetNames[0]];
console.log(XLSX.utils.sheet_to_csv(ws));
});
Complete Example (click to show)
Tested Environments

This demo was last tested on 2024 January 15 against request 2.88.2

  1. Install the NodeJS module
npm i --save https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz [email protected]
  1. Copy the SheetJSRequest.js code snippet to a file SheetJSRequest.js

  2. Run the script:

node SheetJSRequest.js

If successful, the script will print CSV contents of the test file.

axios

When the responseType is "arraybuffer", axios actually captures the data in a NodeJS Buffer. The SheetJS read method handles NodeJS Buffer objects:

SheetJSAxios.js
const XLSX = require("xlsx"), axios = require("axios");

async function workbook_dl_axios(url) {
const res = await axios(url, {responseType:'arraybuffer'});
/* at this point, res.data is a Buffer */
const workbook = XLSX.read(res.data);
return workbook;
}
Complete Example (click to show)
Tested Environments

This demo was last tested on 2024 January 15 against Axios 1.6.5

  1. Install the NodeJS module
npm i --save https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz [email protected]
  1. Save the following to SheetJSAxios.js:
SheetJSAxios.js
const XLSX = require("xlsx"), axios = require("axios");

async function workbook_dl_axios(url) {
const res = await axios(url, {responseType:'arraybuffer'});
/* at this point, res.data is a Buffer */
const workbook = XLSX.read(res.data);
return workbook;
}

(async() => {
const wb = await workbook_dl_axios('https://sheetjs.com/pres.numbers');
/* print the first worksheet to console */
var ws = wb.Sheets[wb.SheetNames[0]];
console.log(XLSX.utils.sheet_to_csv(ws));
})();
  1. Run the script:
node SheetJSAxios.js

If successful, the script will print CSV contents of the test file.

Other Platforms

Other demos show network operations in special platforms:

Footnotes

  1. See read in "Reading Files"

  2. See sheet_to_html in "Utilities"

  3. See dataType in jQuery.ajax in the official jQuery documentation.

  4. See the official jquery.binarytransport.js repo for more details.