--- title: HTTP Uploads pagination_prev: demos/net/network/index pagination_next: demos/net/server/index --- import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; Browsers and other platforms offer solutions for uploading files to servers and cloud storage solutions. Spreadsheets can be written using SheetJS and uploaded. This demo explores file uploads using a number of browser APIs and wrapper libraries. The upload process will generate a sample XLSX workbook, upload the file to [a test server](#test-server), and display the response. :::info pass This demo focuses on uploading files. Other demos cover other HTTP use cases: - ["HTTP Downloads"](/docs/demos/net/network) covers downloading 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 uploads by encoding requests and responses in UTF-8 strings. For AWS, in the "Binary Media Types" section of the API Gateway console, the `"multipart/form-data"` type should be added to ensure that AWS Lambda functions can receive uploads from clients. ::: ## Uploading Binary Data The SheetJS `write` method[^1] generates file data stored in `ArrayBuffer` objects. The `ArrayBuffer` can be added to a `FormData` object. The `FormData` object can be passed along to POST requests. ```mermaid flowchart LR subgraph SheetJS operations wb(((SheetJS\nWorkbook))) ab(XLSX Data\nArrayBuffer) end file(File\nobject) form(FormData\nobject) server[[Server\nrecipient]] wb --> |`write`\n\n| ab ab --> |new\n\n| file file --> |new\nappend\n| form form --> |POST\nrequest| server ``` ```js /* create sample SheetJS workbook object */ var aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; var ws = XLSX.utils.aoa_to_sheet(aoa); var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* export SheetJS workbook object to XLSX file bytes */ var data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); /* build FormData with the generated file */ var fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); // field name ^^^^ file name ^^^^^^^^^^^^ /* send data using XMLHttpRequest */ var req = new XMLHttpRequest(); req.open("POST", "https://s2c.sheetjs.com", true); req.send(fdata); ``` ## Test Server The service is currently hosted on Deno Deploy. The ["Deno Deploy" demo](/docs/demos/cloud/deno#demo) covers the exact steps for deploying the service. The CORS-enabled service handles POST requests by looking for uploaded files in the `"file"` key. If a file is found, the file will be parsed using the SheetJS `read` method[^2] and the first worksheet will be converted to HTML using the `sheet_to_html` method[^3]. ## Browser Demos When the upload button is clicked, the browser will build up a new workbook, generate a XLSX file, upload it to and show the response. If the process was successful, a HTML table will be displayed :::note Tested Deployments Each browser demo was tested in the following environments: | Browser | Date | |:------------|:-----------| | Chrome 120 | 2024-01-15 | | Safari 17.3 | 2024-02-21 | ::: ### XMLHttpRequest This demo uses [the code snippet from the intro](#uploading-binary-data).
Live demo (click to show) This demo starts from an array of arrays of data. When the button is clicked, a workbook file will be generated and uploaded to . The service will return a HTML table. ```jsx live function SheetJSXHRUL() { const [__html, setHTML] = React.useState(""); const [sz, setSz] = React.useState(0); const [csv, setCSV] = React.useState(""); /* raw data */ const aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; /* target URL */ const url = "https://s2c.sheetjs.com"; /* Fetch and update HTML */ const xport = React.useCallback(async() => { try { /* Make SheetJS Workbook from data */ const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* Export to XLSX */ const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); setSz(data.length || data.byteLength); /* Make FormData */ const fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); /* Upload */ /* - create XMLHttpRequest */ const req = new XMLHttpRequest(); req.open("POST", url, true); /* - on success, display the contents */ req.onload = (e) => setHTML(req.responseText); /* - on error, display "Request failed" */ req.onerror = (e) => setHTML("Request failed"); /* - send data */ req.send(fdata); } catch(e) { setHTML(e && e.message || e); } }); /* Display data in CSV form */ React.useEffect(() => { const ws = XLSX.utils.aoa_to_sheet(aoa); setCSV(XLSX.utils.sheet_to_csv(ws)); }, []); return (
CSV Data
{csv}
{sz ? ( <> Generated file size: {sz} bytes
) : ()}
); } ```
### fetch `fetch` takes a second parameter which allows for setting POST request body: ```js /* create sample SheetJS workbook object */ var aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* export SheetJS workbook object to XLSX file bytes */ var data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); /* build FormData with the generated file */ var fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); // field name ^^^^ file name ^^^^^^^^^^^^ /* send data using fetch */ fetch("https://s2c.sheetjs.com", { method: "POST", body: fdata }); ```
Live demo (click to show) This demo uses `fetch` to upload data to . It will parse the workbook and return an HTML table. ```jsx live function SheetJSFetchUL() { const [__html, setHTML] = React.useState(""); const [sz, setSz] = React.useState(0); const [csv, setCSV] = React.useState(""); /* raw data */ const aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; /* target URL */ const url = "https://s2c.sheetjs.com"; /* Fetch and update HTML */ const xport = React.useCallback(async() => { try { /* Make SheetJS Workbook from data */ const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* Export to XLSX */ const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); setSz(data.length || data.byteLength); /* Make FormData */ const fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); /* Upload */ const res = await fetch(url, {method:"POST", body: fdata}); /* Show Server Response */ setHTML((await res.text())); } catch(e) { setHTML(e && e.message || e); }}); /* Display data in CSV form */ React.useEffect(() => { const ws = XLSX.utils.aoa_to_sheet(aoa); setCSV(XLSX.utils.sheet_to_csv(ws)); }, []); return (
CSV Data
{csv}
{sz ? ( <> Generated file size: {sz} bytes
) : ()}
); } ```
### 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. Uploading form data is nearly identical to the `fetch` example: ```js /* create sample SheetJS workbook object */ var aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* export SheetJS workbook object to XLSX file bytes */ var data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); /* build FormData with the generated file */ var fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); // field name ^^^^ file name ^^^^^^^^^^^^ /* send data using axios */ axios("https://s2c.sheetjs.com", { method: "POST", data: fdata }); ```
Live demo (click to show) This demo uses `axios` to upload data to . It will parse the workbook and return 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 SheetJSAxiosUL() { const [__html, setHTML] = React.useState(""); const [sz, setSz] = React.useState(0); const [csv, setCSV] = React.useState(""); /* raw data */ const aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; /* target URL */ const url = "https://s2c.sheetjs.com"; /* Fetch and update HTML */ const xport = React.useCallback(async() => { try { /* Make SheetJS Workbook from data */ const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* Export to XLSX */ const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); setSz(data.length || data.byteLength); /* Make FormData */ const fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); /* Upload */ const res = await axios(url, {method:"POST", data: fdata}); /* Show Server Response */ setHTML(res.data); } catch(e) { setHTML(e && e.message || e); }}); /* Display data in CSV form */ React.useEffect(() => { const ws = XLSX.utils.aoa_to_sheet(aoa); setCSV(XLSX.utils.sheet_to_csv(ws)); }, []); return (
CSV Data
{csv}
{sz ? ( <> Generated file size: {sz} bytes
) : ()}
); } ```
#### superagent [`superagent`](https://ladjs.github.io/superagent/) is a network request library with a "Fluent Interface". The `send` method accepts a `FormData` object as the first argument: ```js /* create sample SheetJS workbook object */ var aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* export SheetJS workbook object to XLSX file bytes */ var data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); /* build FormData with the generated file */ var fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); // field name ^^^^ file name ^^^^^^^^^^^^ /* send data (fd is the FormData object) */ superagent.post("https://s2c.sheetjs.com").send(fd); ```
Live demo (click to show) This demo uses `superagent` to upload data to . It will parse the workbook and return 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 SheetJSSuperAgentUL() { const [__html, setHTML] = React.useState(""); const [sz, setSz] = React.useState(0); const [csv, setCSV] = React.useState(""); /* raw data */ const aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; /* target URL */ const url = "https://s2c.sheetjs.com"; /* Fetch and update HTML */ const xport = React.useCallback(async() => { try { /* Make SheetJS Workbook from data */ const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* Export to XLSX */ const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); setSz(data.length || data.byteLength); /* Make FormData */ const fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); /* Upload */ superagent.post(url).send(fdata).end((err, res) => { /* Show Server Response */ setHTML(res.text); }); } catch(e) { setHTML(e && e.message || e); }}); /* Display data in CSV form */ React.useEffect(() => { const ws = XLSX.utils.aoa_to_sheet(aoa); setCSV(XLSX.utils.sheet_to_csv(ws)); }, []); return (
CSV Data
{csv}
{sz ? ( <> Generated file size: {sz} bytes
) : ()}
); } ```
## NodeJS Demos These examples show how to upload data in NodeJS. ### fetch The `fetch` implementation mirrors the [browser `fetch`](#fetch). :::note Tested Deployments This demo was last tested on 2023 November 19 against NodeJS `20.9.0` :::
Complete Example (click to show) This demo uses `fetch` to upload data to . It will parse the workbook and return data in CSV rows. 1) Install the [SheetJS 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" const XLSX = require("xlsx"); /* create sample SheetJS workbook object */ var aoa = [ ["S", "h", "e", "e", "t", "J", "S"], [ 5, 4, 3, 3, 7, 9, 5] ]; const ws = XLSX.utils.aoa_to_sheet(aoa); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); /* export SheetJS workbook object to XLSX file bytes */ var data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); /* build FormData with the generated file */ var fdata = new FormData(); fdata.append('file', new File([data], 'sheetjs.xlsx')); // field name ^^^^ file name ^^^^^^^^^^^^ fdata.append('type', 'csv'); (async() => { /* send data using fetch */ const res = await fetch("https://s2c.sheetjs.com", { method: "POST", body: fdata }); const txt = await res.text(); console.log(txt); })(); ``` 3) Run the script: ```bash node SheetJSFetch.js ``` It will print CSV contents of the test file.
## Troubleshooting Some SheetJS users have reported corrupted files. To diagnose the error, it is strongly recommended to write local files. For example, using `fetch` in the browser, the bytes can be downloaded using the [HTML5 Download Attribute](/docs/demos/local/file#html5-download-attribute). The highlighted lines should be added immediately after `write`: ```js title="Diagnosing issues in a fetch upload" /* Generate XLSX file */ const data = XLSX.write(wb, {bookType: 'xlsx', type: 'array'}); // highlight-start /* Write to Local File */ const blob = new Blob([data]); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.download = "SheetJS.xlsx"; a.href = url; document.body.appendChild(a); a.click(); document.body.removeChild(a); // highlight-end /* Make FormData */ 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}); ``` If the generated file is valid, then the issue is in the server infrastructure. [^1]: See [`write` in "Writing Files"](/docs/api/write-options) [^2]: See [`read` in "Reading Files"](/docs/api/parse-options) [^3]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output)