Skip to main content

HTTP Network Requests

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.

Third-Party Hosts and Binary Data

Some services like AWS will corrupt raw binary uploads / downloads by encoding requests and responses in UTF-8. Typically, these services have options for disabling this behavior.

For AWS, in the "Binary Media Types" section of the API Gateway console, the following types should be added to ensure smooth uploads and downloads:

  • "multipart/form-data" (for Lambda functions to receive files from clients)
  • "application/vnd.ms-excel" (for Lambda functions to send files to clients)

Downloading Binary Data

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

The APIs generally have a way to control the interpretation of the downloaded data. The arraybuffer response type usually forces the data to be presented as a pure ArrayBuffer which can be parsed directly with XLSX.read.

For example, with fetch:

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

const wb = XLSX.read(ab);

Uploading Binary Data

FormData objects can hold File blobs generated from XLSX.write:

/* generate XLSX file bytes */
var data = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});

/* build FormData with the generated file */
var fdata = new FormData();
fdata.append('data', new File([data], 'sheetjs.xlsx'));
// field name ^^^^ file name ^^^^^^^^^^^^

The FormData object can be passed along to the POST request. For example:

var req = new XMLHttpRequest();
req.open("POST", "/upload", true);
req.send(fdata);

Browser Demos

The included demos focus on an editable table. There are two separate flows:

  • 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 an editable table whose contents match the first worksheet. The table is generated using the sheet_to_html utility with editable:true option

  • When the upload button is clicked, the browser will generate a new worksheet using table_to_book and build up a new workbook. It will then attempt to generate a file, upload it to https://s2c.sheetjs.com and show the response.

XMLHttpRequest

For downloading data, the arraybuffer response type generates an ArrayBuffer that can be viewed as an Uint8Array and fed to XLSX.read using array type:

/* 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

For uploading data, this demo populates a FormData object with an ArrayBuffer generated with the array output type:

/* generate XLSX as array buffer */
var data = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});

/* build FormData with the generated file */
var fd = new FormData();
fd.append('data', new File([data], 'sheetjs.xlsx'));

/* send data */
var req = new XMLHttpRequest();
req.open("POST", url, true);
req.send(fd);
Live Upload demo (click to show)

This demo uses XMLHttpRequest to upload data to https://s2c.sheetjs.com. It will parse the workbook and return an HTML table.

Result
Loading...
Live Editor

fetch

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

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

fetch takes a second parameter which allows for setting POST request body:

// assuming `fdata` is a FormData object from "Uploading Binary Data" section
fetch("/upload", { method: "POST", body: fdata });
Live Upload demo (click to show)

This demo uses fetch to upload data to https://s2c.sheetjs.com. It will parse the workbook and return an HTML table.

Result
Loading...
Live Editor

jQuery

jQuery.ajax ($.ajax) does not support binary data out of the box. A custom ajaxTransport can add required functionality. SheetJS users have reported success with jquery.binarytransport.js.

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

Download Files

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

The axios library presents a Promise interface. Setting responseType to arraybuffer ensures the return type is an ArrayBuffer:

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.

caution

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

Uploading form data is nearly identical to the fetch example:

axios("/upload", { method: "POST", data: fdata });
Live Upload demo (click to show)

This demo uses axios to upload data to https://s2c.sheetjs.com. It will parse the workbook and return an HTML table.

Result
Loading...
Live Editor

superagent

The superagent library usage mirrors XHR:

/* 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.

caution

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

The upload portion only differs in the actual request command:

/* send data (fd is the FormData object) */
superagent.post("/upload").send(fd);
Live Upload demo (click to show)

This demo uses superagent to upload data to https://s2c.sheetjs.com. It will parse the workbook and return an HTML table.

Result
Loading...
Live Editor

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:

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

fetch

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;
}

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

danger

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

Setting the option encoding: null passes raw buffers:

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 succesful, 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));
});

axios

When the responseType is "arraybuffer", axios actually captures the data in a NodeJS Buffer. XLSX.read will transparently handle Buffers:

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;
}