--- title: HTTP Downloads pagination_next: demos/net/upload/index --- import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; `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. :::info pass This demo focuses on downloading files. Other demos cover other HTTP use cases: - ["HTTP Uploads"](/docs/demos/net/upload) covers uploading files - ["HTTP Server Processing"](/docs/demos/net/server) covers HTTP servers ::: :::caution 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` method[^1]. The following example shows the data flow using `fetch` to download files: ```mermaid flowchart LR server[(Remote\nFile)] response(Response\nobject) subgraph SheetJS operations ab(XLSX Data\nArrayBuffer) wb(((SheetJS\nWorkbook))) end server --> |`fetch`\nGET request| response response --> |`arrayBuffer`\n\n| ab ab --> |`read`\n\n| wb ``` ```js /* download data into an ArrayBuffer object */ const res = await fetch("https://docs.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, https://docs.sheetjs.com/pres.numbers will be fetched and parsed. The old table will be replaced with a table whose contents match the first worksheet. The SheetJS `sheet_to_html` method[^2] creates the HTML table. :::note Tested Deployments Each browser demo was tested in the following environments: | Browser | Date | |:------------|:-----------| | Chrome 120 | 2024-01-30 | | Safari 17.2 | 2024-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: ```js /* 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 fetch https://docs.sheetjs.com/pres.numbers and show the data in an HTML table. ```jsx live function SheetJSXHRDL() { const [__html, setHTML] = React.useState(""); /* Fetch and update HTML */ React.useEffect(() => { (async() => { /* Fetch file */ const req = new XMLHttpRequest(); req.open("GET", "https://docs.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 (
); } ```
### fetch For downloading data, `Response#arrayBuffer` resolves to an `ArrayBuffer` that can be converted to `Uint8Array` and passed to the SheetJS `read` method: ```js 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://docs.sheetjs.com/pres.numbers and show the data in an HTML table. ```jsx live function SheetJSFetchDL() { const [__html, setHTML] = React.useState(""); /* Fetch and update HTML */ React.useEffect(() => { (async() => { /* Fetch file */ const res = await fetch("https://docs.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 (
); } ```
### jQuery [jQuery](https://jquery.com/) is a JavaScript library that includes helpers for performing "Ajax" network requests. `jQuery.ajax` (`$.ajax`) does not support binary data out of the box[^3]. A custom `ajaxTransport` can add support. SheetJS users have reported success with `jquery.binarytransport.js`[^4] in IE10. After including the main `jquery.js` and `jquery.binarytransport.js` scripts, `$.ajax` will support `dataType: "binary"` and `processData: false`. **[Live Download Demo](pathname:///jquery/index.html)** In a GET request, the default behavior is to return a `Blob` object. Passing `responseType: "arraybuffer"` returns a proper `ArrayBuffer` object in IE10: ```js $.ajax({ type: "GET", url: "https://docs.sheetjs.com/pres.numbers", /* suppress jQuery post-processing */ // highlight-next-line processData: false, /* use the binary transport */ // highlight-next-line dataType: "binary", /* pass an ArrayBuffer in the callback */ // highlight-next-line responseType: "arraybuffer", success: function (ab) { /* at this point, ab is an ArrayBuffer */ // highlight-next-line 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`](https://axios-http.com/) 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: ```js 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://docs.sheetjs.com/pres.numbers and show the data in an HTML table. :::caution pass 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. ::: ```jsx live 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://docs.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 (
); } ```
#### superagent [`superagent`](https://ladjs.github.io/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`: ```js /* 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://docs.sheetjs.com/pres.numbers and show the data in an HTML table. :::caution pass 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. ::: ```jsx live 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://docs.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 (
); } ```
## 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: ```js title="SheetJSHTTPSGet.js" var https = require("https"), XLSX = require("xlsx"); https.get('https://docs.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) :::note Tested Environments This demo was last tested on 2024 January 15 against NodeJS `20.11.0` ::: 1) Install the [NodeJS module](/docs/getting-started/installation/nodejs) {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} 2) Copy the `SheetJSHTTPSGet.js` code snippet to a file `SheetJSHTTPSGet.js` 3) Run the script: ```bash node SheetJSHTTPSGet.js ``` If successful, the script will print CSV contents of the test file.
### fetch :::caution pass 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: ```js 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) :::note Tested Environments This demo was last tested on 2024 January 15 against NodeJS `20.11.0` ::: 1) Install the [NodeJS module](/docs/getting-started/installation/nodejs) {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} 2) Save the following to `SheetJSFetch.js`: ```js title="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://docs.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)); })(); ``` 3) Run the script: ```bash 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 :::danger pass `request` has been deprecated and should only be used in legacy deployments. ::: Setting the option `encoding: null` passes raw buffers: ```js title="SheetJSRequest.js" var XLSX = require('xlsx'), request = require('request'); var url = 'https://docs.sheetjs.com/pres.numbers'; /* call `request` with the option `encoding: null` */ // highlight-next-line request(url, {encoding: null}, function(err, res, data) { if(err || res.statusCode !== 200) return; /* if the request was successful, parse the data */ // highlight-next-line 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) :::note Tested Environments This demo was last tested on 2024 January 15 against request `2.88.2` ::: 1) Install the [NodeJS module](/docs/getting-started/installation/nodejs) {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz request@2.88.2`} 2) Copy the `SheetJSRequest.js` code snippet to a file `SheetJSRequest.js` 3) Run the script: ```bash 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: ```js title="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) :::note Tested Environments This demo was last tested on 2024 January 15 against Axios `1.6.5` ::: 1) Install the [NodeJS module](/docs/getting-started/installation/nodejs) {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz axios@1.6.5`} 2) Save the following to `SheetJSAxios.js`: ```js title="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://docs.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)); })(); ``` 3) Run the script: ```bash 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: - [React Native "Fetching Remote Data"](/docs/demos/mobile/reactnative#fetching-remote-data) - [NativeScript "Fetching Remote Files"](/docs/demos/mobile/nativescript#fetching-remote-files) - [AngularJS "Remote Files"](/docs/demos/frontend/angularjs#remote-files) - [Dojo Toolkit "Parsing Remote Files"](/docs/demos/frontend/dojo#parsing-remote-files) [^1]: See [`read` in "Reading Files"](/docs/api/parse-options) [^2]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output) [^3]: See [`dataType` in `jQuery.ajax`](https://api.jquery.com/jQuery.ajax/) in the official jQuery documentation. [^4]: See [the official `jquery.binarytransport.js` repo](https://github.com/henrya/js-jquery/tree/master/BinaryTransport) for more details.