2023-11-20 02:51:39 +00:00
|
|
|
---
|
|
|
|
title: HTTP Uploads
|
|
|
|
pagination_prev: demos/net/network/index
|
|
|
|
pagination_next: demos/net/server/index
|
|
|
|
---
|
|
|
|
|
|
|
|
<head>
|
2024-01-17 20:22:38 +00:00
|
|
|
<script src="https://unpkg.com/axios@1.6.5/dist/axios.min.js"></script>
|
2023-11-20 02:51:39 +00:00
|
|
|
<script src="https://unpkg.com/superagent@8.1.2/dist/superagent.min.js"></script>
|
|
|
|
</head>
|
|
|
|
|
|
|
|
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
|
2024-04-08 03:55:10 +00:00
|
|
|
file to [a test server](https://s2c.sheetjs.com), and display the response.
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
:::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
|
|
|
|
```
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
### Generating Files
|
|
|
|
|
|
|
|
In a typical scenario, a process generates arrays of simple objects.
|
|
|
|
|
|
|
|
The SheetJS `json_to_sheet` method[^2] generates a SheetJS worksheet object[^3].
|
|
|
|
The `book_new` method[^4] creates a workbook object that includes the worksheet.
|
|
|
|
|
|
|
|
The `write` method[^5] generates the file in memory.
|
|
|
|
|
|
|
|
The following snippet creates a sample dataset and generates an `ArrayBuffer`
|
|
|
|
object representing the workbook bytes:
|
|
|
|
|
|
|
|
```js title="Generating an XLSX file in memory"
|
2023-11-20 02:51:39 +00:00
|
|
|
/* 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);
|
2024-04-08 03:55:10 +00:00
|
|
|
var wb = XLSX.utils.book_new(ws, "Sheet1");
|
2023-11-20 02:51:39 +00:00
|
|
|
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'});
|
2024-04-08 03:55:10 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
### Creating Form Data
|
|
|
|
|
|
|
|
`File` objects represent files. The `File` constructor accepts an array of data
|
|
|
|
fragments and a filename.
|
|
|
|
|
|
|
|
Browser APIs typically represent form body data using `FormData` objects. The
|
|
|
|
`append` method adds fields to the `FormData` object. Adding `File` objects
|
|
|
|
effectively "attaches" a file in the upload.
|
|
|
|
|
|
|
|
The following snippet constructs a new `FormData` object. The `file` field in
|
|
|
|
the form will be set to the data from the previous snippet:
|
|
|
|
|
|
|
|
```js title="Creating Form Data and attaching the generated file"
|
|
|
|
/* create File */
|
|
|
|
var file = new File([data], 'sheetjs.xlsx')
|
|
|
|
// generated XLSX ^^^^ ^^^^^^^^^^^^ file name
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
/* build FormData with the generated file */
|
|
|
|
var fdata = new FormData();
|
2024-04-08 03:55:10 +00:00
|
|
|
fdata.append('file', file);
|
|
|
|
// ^^^^ field name in the form body
|
|
|
|
```
|
2023-11-20 02:51:39 +00:00
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
### POST Request
|
|
|
|
|
|
|
|
This demo explores a number of APIs and libraries for making POST requests. Each
|
|
|
|
approach will upload data stored in `FormData` objects.
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
This snippet uses `XMLHttpRequest` to upload data to https://s2c.sheetjs.com:
|
2024-04-08 03:55:10 +00:00
|
|
|
|
|
|
|
```js title="Uploading Form Data with XMLHttpRequest"
|
2023-11-20 02:51:39 +00:00
|
|
|
/* send data using XMLHttpRequest */
|
|
|
|
var req = new XMLHttpRequest();
|
|
|
|
req.open("POST", "https://s2c.sheetjs.com", true);
|
|
|
|
req.send(fdata);
|
|
|
|
```
|
|
|
|
|
|
|
|
## Browser Demos
|
|
|
|
|
|
|
|
When the upload button is clicked, the browser will build up a new workbook,
|
2024-04-08 04:47:04 +00:00
|
|
|
generate a XLSX file, upload it to https://s2c.sheetjs.com and show the
|
2023-11-20 02:51:39 +00:00
|
|
|
response. If the process was successful, a HTML table will be displayed
|
|
|
|
|
|
|
|
:::note Tested Deployments
|
|
|
|
|
2024-01-17 20:22:38 +00:00
|
|
|
Each browser demo was tested in the following environments:
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
| Browser | Date |
|
|
|
|
|:------------|:-----------|
|
2024-06-20 07:30:34 +00:00
|
|
|
| Chrome 126 | 2024-06-19 |
|
|
|
|
| Safari 17.3 | 2024-06-19 |
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
:::
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
#### Test Server
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
The https://s2c.sheetjs.com service is currently hosted on Deno Deploy. The
|
2024-04-08 03:55:10 +00:00
|
|
|
["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[^6] and the first worksheet will be converted to HTML using the
|
|
|
|
`sheet_to_html` method[^7].
|
|
|
|
|
2024-01-17 20:22:38 +00:00
|
|
|
### XMLHttpRequest
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
Using the `XMLHttpRequest` API, the `send` method can accept `FormData` objects:
|
|
|
|
|
|
|
|
```js title="Uploading Form Data with XMLHttpRequest"
|
|
|
|
/* send data using XMLHttpRequest */
|
|
|
|
var req = new XMLHttpRequest();
|
|
|
|
req.open("POST", "https://s2c.sheetjs.com", true);
|
|
|
|
req.send(fdata);
|
|
|
|
```
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Complete Code Snippet</b> (click to show)</summary>
|
2024-04-08 03:55:10 +00:00
|
|
|
|
|
|
|
```js title="SheetJS + XMLHttpRequest example"
|
|
|
|
/* 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 XMLHttpRequest */
|
|
|
|
var req = new XMLHttpRequest();
|
|
|
|
req.open("POST", "https://s2c.sheetjs.com", true);
|
|
|
|
req.send(fdata);
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
2024-01-17 20:22:38 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Live demo</b> (click to show)</summary>
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
This demo starts from an array of arrays of data. When the button is clicked, a
|
2024-04-08 04:47:04 +00:00
|
|
|
workbook file will be generated and uploaded to https://s2c.sheetjs.com. The
|
2023-11-20 02:51:39 +00:00
|
|
|
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 ( <pre><b>CSV Data</b><div>{csv}</div>
|
|
|
|
{sz ? ( <>
|
|
|
|
<b>Generated file size: {sz} bytes</b>
|
|
|
|
<div dangerouslySetInnerHTML={{ __html }}/>
|
|
|
|
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
|
|
|
</pre> );
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
### fetch
|
|
|
|
|
|
|
|
`fetch` takes a second parameter which allows for setting POST request body:
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
```js title="Uploading Form Data with fetch"
|
|
|
|
/* send data using fetch */
|
|
|
|
fetch("https://s2c.sheetjs.com", { method: "POST", body: fdata });
|
|
|
|
```
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Complete Code Snippet</b> (click to show)</summary>
|
2024-04-08 03:55:10 +00:00
|
|
|
|
|
|
|
```js title="SheetJS + fetch example"
|
2023-11-20 02:51:39 +00:00
|
|
|
/* 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 });
|
|
|
|
```
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
</details>
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Live demo</b> (click to show)</summary>
|
2023-11-20 02:51:39 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
This demo uses `fetch` to upload data to https://s2c.sheetjs.com. It will parse
|
2023-11-20 02:51:39 +00:00
|
|
|
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 (<pre><b>CSV Data</b><div>{csv}</div>
|
|
|
|
{sz ? ( <>
|
|
|
|
<b>Generated file size: {sz} bytes</b>
|
|
|
|
<div dangerouslySetInnerHTML={{ __html }}/>
|
|
|
|
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
|
|
|
</pre>);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
### 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:
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
```js title="Uploading Form Data with axios"
|
|
|
|
/* send data using axios */
|
|
|
|
axios("https://s2c.sheetjs.com", { method: "POST", body: fdata });
|
|
|
|
```
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Complete Code Snippet</b> (click to show)</summary>
|
2024-04-08 03:55:10 +00:00
|
|
|
|
|
|
|
```js title="SheetJS + axios example"
|
2023-11-20 02:51:39 +00:00
|
|
|
/* 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 });
|
|
|
|
```
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
</details>
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Live demo</b> (click to show)</summary>
|
2023-11-20 02:51:39 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
This demo uses `axios` to upload data to https://s2c.sheetjs.com. It will parse
|
2023-11-20 02:51:39 +00:00
|
|
|
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 (<pre><b>CSV Data</b><div>{csv}</div>
|
|
|
|
{sz ? ( <>
|
|
|
|
<b>Generated file size: {sz} bytes</b>
|
|
|
|
<div dangerouslySetInnerHTML={{ __html }}/>
|
|
|
|
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
|
|
|
</pre>);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
#### superagent
|
|
|
|
|
2024-01-17 20:22:38 +00:00
|
|
|
[`superagent`](https://ladjs.github.io/superagent/) is a network request library
|
|
|
|
with a "Fluent Interface".
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
The `send` method accepts a `FormData` object as the first argument:
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
```js title="Uploading Form Data with superagent"
|
|
|
|
/* send data using superagent */
|
|
|
|
superagent.post("https://s2c.sheetjs.com").send(fd);
|
|
|
|
```
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Complete Code Snippet</b> (click to show)</summary>
|
2024-04-08 03:55:10 +00:00
|
|
|
|
|
|
|
```js title="SheetJS + superagent example"
|
2023-11-20 02:51:39 +00:00
|
|
|
/* 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);
|
|
|
|
```
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
</details>
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Live demo</b> (click to show)</summary>
|
2023-11-20 02:51:39 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
This demo uses `superagent` to upload data to https://s2c.sheetjs.com. It will
|
2023-11-20 02:51:39 +00:00
|
|
|
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 (<pre><b>CSV Data</b><div>{csv}</div>
|
|
|
|
{sz ? ( <>
|
|
|
|
<b>Generated file size: {sz} bytes</b>
|
|
|
|
<div dangerouslySetInnerHTML={{ __html }}/>
|
|
|
|
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
|
|
|
</pre>);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
## NodeJS Demos
|
|
|
|
|
|
|
|
These examples show how to upload data in NodeJS.
|
|
|
|
|
|
|
|
### fetch
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
NodeJS `fetch`, available in version 20, mirrors the [browser `fetch`](#fetch).
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
:::note Tested Deployments
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
This demo was tested in the following environments:
|
|
|
|
|
|
|
|
| NodeJS | Date |
|
|
|
|
|:-----------|:-----------|
|
|
|
|
| `20.12.1` | 2024-04-07 |
|
|
|
|
| `21.7.2` | 2024-04-07 |
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
:::
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Complete Example</b> (click to show)</summary>
|
2023-11-20 02:51:39 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
This demo uses `fetch` to upload data to https://s2c.sheetjs.com. It will parse
|
2023-11-20 02:51:39 +00:00
|
|
|
the workbook and return data in CSV rows.
|
|
|
|
|
|
|
|
1) Install the [SheetJS NodeJS module](/docs/getting-started/installation/nodejs):
|
|
|
|
|
|
|
|
<CodeBlock language="bash">{`\
|
|
|
|
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
|
|
|
</CodeBlock>
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2024-04-08 03:55:10 +00:00
|
|
|
### request
|
|
|
|
|
|
|
|
The deprecated [`request`](https://github.com/request/request) library is useful
|
|
|
|
in legacy NodeJS deployments where `fetch` may not be available.
|
|
|
|
|
|
|
|
The SheetJS `write` method will generate NodeJS Buffer objects when the `type`
|
|
|
|
option is set to `"buffer"`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* export SheetJS workbook object to XLSX file bytes */
|
|
|
|
const data = XLSX.write(wb, {bookType: 'xlsx', type: 'buffer'});
|
|
|
|
```
|
|
|
|
|
|
|
|
A `request` file object can be built using the Buffer. The file object must
|
|
|
|
include an `options` object that specifies the file name and content type:
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* create a file object for the `request` form data */
|
|
|
|
const request_file = {
|
|
|
|
/* `value` can be a Buffer object */
|
|
|
|
value: data,
|
|
|
|
options: {
|
|
|
|
/* `options.filename` is the filename that the server will see */
|
|
|
|
filename: "sheetjs.xlsx",
|
|
|
|
/* `options.contentType` must be set */
|
|
|
|
contentType: "application/octet-stream"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
The `request` and `request.post` methods accept an options argument. The
|
|
|
|
`formData` property specifies the body to be uploaded. Property names correspond
|
|
|
|
to the uploaded form names and values describe the uploaded content.
|
|
|
|
|
|
|
|
The `request` file object should be added to the `formData` object:
|
|
|
|
|
|
|
|
```js
|
|
|
|
request({
|
|
|
|
// ... other options ...
|
|
|
|
formData: {
|
|
|
|
// ... other form fields ...
|
|
|
|
|
|
|
|
/* the server will see the uploaded file in the `file` body property */
|
|
|
|
/* highlight-next-line */
|
|
|
|
file: request_file
|
|
|
|
}
|
|
|
|
}, function(err, res) { /* handle response ... */ });
|
|
|
|
```
|
|
|
|
|
|
|
|
:::note Tested Deployments
|
|
|
|
|
|
|
|
This demo was tested in the following environments:
|
|
|
|
|
|
|
|
| NodeJS | `request` | Date |
|
|
|
|
|:-----------|:----------|:-----------|
|
|
|
|
| `0.10.48` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `0.12.18` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `4.9.1` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `6.17.1` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `8.17.0` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `10.24.1` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `12.22.12` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `14.21.3` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `16.20.2` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `18.20.1` | `2.88.2` | 2024-04-07 |
|
|
|
|
| `20.12.1` | `2.88.2` | 2024-04-07 |
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Complete Example</b> (click to show)</summary>
|
2024-04-08 03:55:10 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
This demo uses `request` to upload data to https://s2c.sheetjs.com. It will
|
2024-04-08 03:55:10 +00:00
|
|
|
parse the workbook and return data in CSV rows.
|
|
|
|
|
|
|
|
1) Install the [SheetJS NodeJS module](/docs/getting-started/installation/nodejs)
|
|
|
|
and `request` module:
|
|
|
|
|
|
|
|
<CodeBlock language="bash">{`\
|
|
|
|
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz request`}
|
|
|
|
</CodeBlock>
|
|
|
|
|
|
|
|
2) Save the following to `SheetJSRequest.js`:
|
|
|
|
|
|
|
|
```js title="SheetJSRequest.js"
|
|
|
|
const XLSX = require("xlsx");
|
|
|
|
const request = require("request");
|
|
|
|
|
|
|
|
/* 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: 'buffer'});
|
|
|
|
|
|
|
|
request({
|
|
|
|
method: "POST",
|
|
|
|
url: "https://s2c.sheetjs.com",
|
|
|
|
headers: {
|
|
|
|
Accept: "text/html"
|
|
|
|
},
|
|
|
|
formData: {
|
|
|
|
type: "csv",
|
|
|
|
file: {
|
|
|
|
value: data,
|
|
|
|
options: {
|
|
|
|
filename: "sheetjs.xlsx",
|
|
|
|
contentType: "application/octet-stream"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, function(err, res, body) {
|
|
|
|
if(err) return console.error(err);
|
|
|
|
console.log(body);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
3) Run the script:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
node SheetJSRequest.js
|
|
|
|
```
|
|
|
|
|
|
|
|
It will print CSV contents of the test file.
|
|
|
|
|
|
|
|
:::caution pass
|
|
|
|
|
|
|
|
For legacy versions of NodeJS, the process may fail with a certificate error:
|
|
|
|
|
|
|
|
```
|
|
|
|
{ [Error: certificate not trusted] code: 'CERT_UNTRUSTED' }
|
|
|
|
```
|
|
|
|
|
|
|
|
The environment variable `NODE_TLS_REJECT_UNAUTHORIZED` can be set to `0`:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
env NODE_TLS_REJECT_UNAUTHORIZED="0" node SheetJSRequest.js
|
|
|
|
```
|
|
|
|
|
|
|
|
**It is strongly recommended to upgrade to a newer version of NodeJS!**
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
</details>
|
2023-11-20 02:51:39 +00:00
|
|
|
|
|
|
|
## 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)
|
2024-04-08 03:55:10 +00:00
|
|
|
[^2]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
|
|
|
[^3]: See ["Worksheet Object" in "SheetJS Data Model"](/docs/csf/sheet) for more details.
|
|
|
|
[^4]: See [`book_new` in "Utilities"](/docs/api/utilities/wb)
|
|
|
|
[^5]: See [`write` in "Writing Files"](/docs/api/write-options)
|
|
|
|
[^6]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
|
|
|
[^7]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output)
|