| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: HTTP Network Requests | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <head> | 
					
						
							|  |  |  |   <script src="https://unpkg.com/axios/dist/axios.min.js"></script> | 
					
						
							|  |  |  |   <script src="https://unpkg.com/superagent@7.1.1/dist/superagent.min.js"></script> | 
					
						
							|  |  |  | </head> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-13 22:01:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | `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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution 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`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const res = await fetch("https://sheetjs.com/pres.numbers"); | 
					
						
							| 
									
										
										
										
											2022-08-14 02:10:41 +00:00
										 |  |  | const ab = await res.arrayBuffer(); // recover data as ArrayBuffer | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | const wb = XLSX.read(ab); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Uploading Binary Data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `FormData` objects can hold `File` blobs generated from `XLSX.write`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```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(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Download demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `XMLHttpRequest` to download <https://sheetjs.com/pres.numbers> | 
					
						
							|  |  |  | and show the data in an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSXHRDL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* 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(); | 
					
						
							|  |  |  |   }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |   return ( <div dangerouslySetInnerHTML={{ __html }}/> ); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For uploading data, this demo populates a `FormData` object with an ArrayBuffer | 
					
						
							|  |  |  | generated with the `array` output type: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* 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); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Upload demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `XMLHttpRequest` to upload data to <https://s2c.sheetjs.com>.  It | 
					
						
							|  |  |  | will parse the workbook and return an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSXHRUL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   const [sz, setSz] = React.useState(0); | 
					
						
							|  |  |  |   const csv = "a,b,c\n1,2,3"; | 
					
						
							|  |  |  |   /* Fetch and update HTML */ | 
					
						
							|  |  |  |   const xport = React.useCallback(async() => { | 
					
						
							|  |  |  |     /* Make Workbook from CSV */ | 
					
						
							|  |  |  |     const wb = XLSX.read(csv, { type: "string" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Make FormData */ | 
					
						
							|  |  |  |     const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); | 
					
						
							|  |  |  |     setSz(data.length || data.byteLength); | 
					
						
							|  |  |  |     const fdata = new FormData(); | 
					
						
							|  |  |  |     fdata.append('file', new File([data], 'sheetjs.xlsx')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Upload */ | 
					
						
							|  |  |  |     const url = "https://s2c.sheetjs.com"; | 
					
						
							|  |  |  |     const req = new XMLHttpRequest(); | 
					
						
							|  |  |  |     req.open("POST", url, true); | 
					
						
							|  |  |  |     req.onload = (e) => setHTML(req.responseText); | 
					
						
							|  |  |  |     req.send(fdata); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (<pre> | 
					
						
							|  |  |  |     <b>CSV Data</b> | 
					
						
							|  |  |  |     <div>{csv}</div> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     {sz ? ( <> | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |       <b>Generated file size: {sz} bytes</b> | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |       <div dangerouslySetInnerHTML={{ __html }}/> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     </> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)} | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   </pre>); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### fetch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For downloading data, `Response#arrayBuffer` resolves to an `ArrayBuffer` that | 
					
						
							|  |  |  | can be converted to `Uint8Array` and passed to `XLSX.read`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```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 */ | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Download demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `fetch` to download <https://sheetjs.com/pres.numbers> and show | 
					
						
							|  |  |  | the data in an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSFetchDL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* 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)); | 
					
						
							|  |  |  |   }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |   return ( <div dangerouslySetInnerHTML={{ __html }}/> ); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `fetch` takes a second parameter which allows for setting POST request body: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | // assuming `fdata` is a FormData object from "Uploading Binary Data" section | 
					
						
							|  |  |  | fetch("/upload", { method: "POST", body: fdata }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Upload demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `fetch` to upload data to <https://s2c.sheetjs.com>.  It will parse | 
					
						
							|  |  |  | the workbook and return an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSFetchUL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   const [sz, setSz] = React.useState(0); | 
					
						
							|  |  |  |   const csv = "a,b,c\n1,2,3"; | 
					
						
							|  |  |  |   /* Fetch and update HTML */ | 
					
						
							|  |  |  |   const xport = React.useCallback(async(e) => { | 
					
						
							|  |  |  |     /* Make Workbook from CSV */ | 
					
						
							|  |  |  |     const wb = XLSX.read(csv, { type: "string" }); | 
					
						
							|  |  |  |     const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Make FormData */ | 
					
						
							|  |  |  |     setSz(data.length || data.byteLength); | 
					
						
							|  |  |  |     const fdata = new FormData(); | 
					
						
							|  |  |  |     fdata.append('file', new File([data], 'sheetjs.xlsx')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Upload */ | 
					
						
							|  |  |  |     const url = "https://s2c.sheetjs.com"; | 
					
						
							|  |  |  |     const res = await fetch(url, {method:"POST", body: fdata}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Set HTML */ | 
					
						
							|  |  |  |     setHTML((await res.text())); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (<pre> | 
					
						
							|  |  |  |     <b>CSV Data</b> | 
					
						
							|  |  |  |     <div>{csv}</div> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     {sz ? ( <> | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |       <b>Generated file size: {sz} bytes</b> | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |       <div dangerouslySetInnerHTML={{ __html }}/> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     </> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)} | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   </pre>); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-20 18:30:42 +00:00
										 |  |  | ### jQuery | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `jQuery.ajax` (`$.ajax`) does not support binary data out of the box. A custom | 
					
						
							|  |  |  | `ajaxTransport` can add required functionality. SheetJS users have reported | 
					
						
							| 
									
										
										
										
											2023-04-19 20:03:23 +00:00
										 |  |  | success with `jquery.binarytransport.js` in IE10. | 
					
						
							| 
									
										
										
										
											2023-03-20 18:30:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | After including the main `jquery.js` and `jquery.binarytransport.js` scripts, | 
					
						
							|  |  |  | `$.ajax` will support `dataType: "binary"` and `processData: false`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Download Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **[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://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); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | ### 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | async function workbook_dl_axios(url) { | 
					
						
							|  |  |  |   const res = await axios(url, {responseType:'arraybuffer'}); | 
					
						
							|  |  |  |   const workbook = XLSX.read(res.data); | 
					
						
							|  |  |  |   return workbook; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Download demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `axios` to download <https://sheetjs.com/pres.numbers> and show | 
					
						
							|  |  |  | the data in an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-18 02:33:30 +00:00
										 |  |  | :::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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSAxiosDL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Fetch and update HTML */ | 
					
						
							|  |  |  |   React.useEffect(async() => { | 
					
						
							|  |  |  |     /* 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)); | 
					
						
							|  |  |  |   }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |   return ( <div dangerouslySetInnerHTML={{ __html }}/> ); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Uploading form data is nearly identical to the `fetch` example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | axios("/upload", { method: "POST", data: fdata }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Upload demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `axios` to upload data to <https://s2c.sheetjs.com>.  It will parse | 
					
						
							|  |  |  | the workbook and return an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSAxiosUL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   const [sz, setSz] = React.useState(0); | 
					
						
							|  |  |  |   const csv = "a,b,c\n1,2,3"; | 
					
						
							|  |  |  |   /* Fetch and update HTML */ | 
					
						
							|  |  |  |   const xport = React.useCallback(async() => { | 
					
						
							|  |  |  |     /* Make Workbook from CSV */ | 
					
						
							|  |  |  |     const wb = XLSX.read(csv, { type: "string" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Make FormData */ | 
					
						
							|  |  |  |     const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); | 
					
						
							|  |  |  |     setSz(data.length || data.byteLength); | 
					
						
							|  |  |  |     const fdata = new FormData(); | 
					
						
							|  |  |  |     fdata.append('file', new File([data], 'sheetjs.xlsx')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Upload */ | 
					
						
							|  |  |  |     const url = "https://s2c.sheetjs.com"; | 
					
						
							|  |  |  |     const res = await axios(url, {method:"POST", data: fdata}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Set HTML */ | 
					
						
							|  |  |  |     setHTML(res.data); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (<pre> | 
					
						
							|  |  |  |     <b>CSV Data</b> | 
					
						
							|  |  |  |     <div>{csv}</div> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     {sz ? ( <> | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |       <b>Generated file size: {sz} bytes</b> | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |       <div dangerouslySetInnerHTML={{ __html }}/> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     </> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)} | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   </pre>); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-13 22:01:26 +00:00
										 |  |  | #### superagent | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The `superagent` library usage mirrors XHR: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```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 */ | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Download demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `superagent` to download <https://sheetjs.com/pres.numbers> and | 
					
						
							|  |  |  | show the data in an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-18 02:33:30 +00:00
										 |  |  | :::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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSSuperAgentDL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Fetch and update HTML */ | 
					
						
							|  |  |  |   React.useEffect(async() => { | 
					
						
							|  |  |  |     /* 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)); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |   }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |   return ( <div dangerouslySetInnerHTML={{ __html }}/> ); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The upload portion only differs in the actual request command: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* send data (fd is the FormData object) */ | 
					
						
							|  |  |  | superagent.post("/upload").send(fd); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Live Upload demo</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses `superagent` to upload data to <https://s2c.sheetjs.com>.  It will | 
					
						
							|  |  |  | parse the workbook and return an HTML table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSSuperAgentUL() { | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |   const [__html, setHTML] = React.useState(""); | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   const [sz, setSz] = React.useState(0); | 
					
						
							|  |  |  |   const csv = "a,b,c\n1,2,3"; | 
					
						
							|  |  |  |   /* Fetch and update HTML */ | 
					
						
							|  |  |  |   const xport = React.useCallback(async() => { | 
					
						
							|  |  |  |     /* Make Workbook from CSV */ | 
					
						
							|  |  |  |     const wb = XLSX.read(csv, { type: "string" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Make FormData */ | 
					
						
							|  |  |  |     const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); | 
					
						
							|  |  |  |     setSz(data.length || data.byteLength); | 
					
						
							|  |  |  |     const fdata = new FormData(); | 
					
						
							|  |  |  |     fdata.append('file', new File([data], 'sheetjs.xlsx')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Upload */ | 
					
						
							|  |  |  |     const url = "https://s2c.sheetjs.com"; | 
					
						
							|  |  |  |     superagent.post(url).send(fdata).end((err, res) => { | 
					
						
							|  |  |  |       /* Set HTML */ | 
					
						
							|  |  |  |       setHTML(res.text); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (<pre> | 
					
						
							|  |  |  |     <b>CSV Data</b> | 
					
						
							|  |  |  |     <div>{csv}</div> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     {sz ? ( <> | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |       <b>Generated file size: {sz} bytes</b> | 
					
						
							| 
									
										
										
										
											2022-10-21 00:10:10 +00:00
										 |  |  |       <div dangerouslySetInnerHTML={{ __html }}/> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |     </> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)} | 
					
						
							| 
									
										
										
										
											2022-08-05 05:10:11 +00:00
										 |  |  |   </pre>); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							| 
									
										
										
										
											2022-08-21 00:46:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## NodeJS Demos | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-11 08:53:04 +00:00
										 |  |  | These examples show how to download data in NodeJS. | 
					
						
							| 
									
										
										
										
											2022-08-21 00:46:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-11 08:53:04 +00:00
										 |  |  | ### HTTPS GET | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `https` module provides a low-level `get` method for HTTPS GET requests: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```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)); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### fetch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### 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 | 
					
						
							| 
									
										
										
										
											2022-08-21 00:46:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | :::warning | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `request` has been deprecated and should only be used in legacy deployments. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Setting the option `encoding: null` passes raw buffers: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var XLSX = require('xlsx'), request = require('request'); | 
					
						
							|  |  |  | var url = 'https://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 succesful, parse the data */ | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   var wb = XLSX.read(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* print the first worksheet to console */ | 
					
						
							|  |  |  |   var ws = wb.Sheets[wb.SheetNames[0]]; | 
					
						
							| 
									
										
										
										
											2022-11-11 08:53:04 +00:00
										 |  |  |   console.log(XLSX.utils.sheet_to_csv(ws)); | 
					
						
							| 
									
										
										
										
											2022-08-21 00:46:10 +00:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-11-11 08:53:04 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### axios | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the `responseType` is `"arraybuffer"`, `axios` actually captures the data | 
					
						
							|  |  |  | in a NodeJS Buffer.  `XLSX.read` will transparently handle Buffers: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` |