upload
This commit is contained in:
parent
8f9512b217
commit
7e88f2db0b
5
docz/docs/03-demos/03-net/01-network/_category_.json
Normal file
5
docz/docs/03-demos/03-net/01-network/_category_.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"label": "HTTP Downloads",
|
||||
"collapsed": false,
|
||||
"position": 1
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: HTTP Network Requests
|
||||
pagination_next: demos/net/server/index
|
||||
title: HTTP Downloads
|
||||
pagination_next: demos/net/upload/index
|
||||
---
|
||||
|
||||
<head>
|
||||
@ -11,6 +11,15 @@ pagination_next: demos/net/server/index
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
:::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
|
||||
|
||||
:::
|
||||
|
||||
`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
|
||||
@ -18,15 +27,12 @@ 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.
|
||||
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
|
||||
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)
|
||||
`"application/vnd.ms-excel"` type should be added to ensure that AWS Lambda
|
||||
functions functions can send files to clients.
|
||||
|
||||
:::
|
||||
|
||||
@ -37,51 +43,28 @@ 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`.
|
||||
as an `ArrayBuffer` which can be parsed directly with the SheetJS `read` method[^1].
|
||||
|
||||
For example, with `fetch`:
|
||||
|
||||
```js
|
||||
/* download data into an ArrayBuffer object */
|
||||
const res = await fetch("https://sheetjs.com/pres.numbers");
|
||||
const ab = await res.arrayBuffer(); // recover data as ArrayBuffer
|
||||
|
||||
/* parse file */
|
||||
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:
|
||||
The included demos focus on an editable table.
|
||||
|
||||
- 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 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 a table whose
|
||||
contents match the first worksheet. The table is generated using the SheetJS
|
||||
`sheet_to_html` method[^2]
|
||||
|
||||
- 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
|
||||
|
||||
@ -135,64 +118,6 @@ function SheetJSXHRDL() {
|
||||
|
||||
</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() {
|
||||
const [__html, setHTML] = React.useState("");
|
||||
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>
|
||||
{sz ? ( <>
|
||||
<b>Generated file size: {sz} bytes</b>
|
||||
<div dangerouslySetInnerHTML={{ __html }}/>
|
||||
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
||||
</pre>);
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### fetch
|
||||
|
||||
@ -242,69 +167,17 @@ function SheetJSFetchDL() {
|
||||
|
||||
</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() {
|
||||
const [__html, setHTML] = React.useState("");
|
||||
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>
|
||||
{sz ? ( <>
|
||||
<b>Generated file size: {sz} bytes</b>
|
||||
<div dangerouslySetInnerHTML={{ __html }}/>
|
||||
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
||||
</pre>);
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
### 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[^1]. A custom `ajaxTransport` can add support.
|
||||
binary data out of the box[^3]. A custom `ajaxTransport` can add support.
|
||||
|
||||
SheetJS users have reported success with `jquery.binarytransport.js`[^2] in IE10.
|
||||
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`.
|
||||
|
||||
_Download Files_
|
||||
|
||||
**[Live Download Demo](pathname:///jquery/index.html)**
|
||||
|
||||
In a GET request, the default behavior is to return a `Blob` object. Passing
|
||||
@ -399,58 +272,10 @@ function SheetJSAxiosDL() {
|
||||
|
||||
</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() {
|
||||
const [__html, setHTML] = React.useState("");
|
||||
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>
|
||||
{sz ? ( <>
|
||||
<b>Generated file size: {sz} bytes</b>
|
||||
<div dangerouslySetInnerHTML={{ __html }}/>
|
||||
</> ) : (<button onClick={xport}><b>Export and Upload!</b></button>)}
|
||||
</pre>);
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### superagent
|
||||
|
||||
[`superagent`](https://github.com/visionmedia/superagent) is a network request
|
||||
library with a "Fluent Interface"[^3]. Calling the `responseType` method with
|
||||
library with a "Fluent Interface". Calling the `responseType` method with
|
||||
`"arraybuffer"` will ensure the final response object is an `ArrayBuffer`:
|
||||
|
||||
```js
|
||||
@ -512,56 +337,6 @@ function SheetJSSuperAgentDL() {
|
||||
|
||||
</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() {
|
||||
const [__html, setHTML] = React.useState("");
|
||||
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>
|
||||
{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 download data in NodeJS.
|
||||
@ -774,6 +549,7 @@ 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)
|
||||
|
||||
[^1]: See [`dataType` in `jQuery.ajax`](https://api.jquery.com/jQuery.ajax/) in the official jQuery documentation.
|
||||
[^2]: See [the official `jquery.binarytransport.js` repo](https://github.com/henrya/js-jquery/tree/master/BinaryTransport) for more details.
|
||||
[^3]: See ["Fluent interface"](https://en.wikipedia.org/wiki/Fluent_interface) on Wikipedia.
|
||||
[^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.
|
5
docz/docs/03-demos/03-net/02-upload/_category_.json
Normal file
5
docz/docs/03-demos/03-net/02-upload/_category_.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"label": "HTTP Uploads",
|
||||
"collapsed": false,
|
||||
"position": 2
|
||||
}
|
608
docz/docs/03-demos/03-net/02-upload/index.mdx
Normal file
608
docz/docs/03-demos/03-net/02-upload/index.mdx
Normal file
@ -0,0 +1,608 @@
|
||||
---
|
||||
title: HTTP Uploads
|
||||
pagination_prev: demos/net/network/index
|
||||
pagination_next: demos/net/server/index
|
||||
---
|
||||
|
||||
<head>
|
||||
<script src="https://unpkg.com/axios@1.6.2/dist/axios.min.js"></script>
|
||||
<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
|
||||
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 <https://s2c.sheetjs.com> 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 <https://s2c.sheetjs.com> and show the
|
||||
response. If the process was successful, a HTML table will be displayed
|
||||
|
||||
### XMLHttpRequest
|
||||
|
||||
This demo uses [the code snippet from the intro](#uploading-binary-data).
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This browser demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:------------|:-----------|
|
||||
| Chrome 119 | 2023-11-19 |
|
||||
| Safari 17.1 | 2023-11-19 |
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Live demo</b> (click to show)</summary>
|
||||
|
||||
This demo starts from an array of arrays of data. When the button is clicked, a
|
||||
workbook file will be generated and uploaded to <https://s2c.sheetjs.com>. 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 ( <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:
|
||||
|
||||
```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 });
|
||||
```
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This browser demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:------------|:-----------|
|
||||
| Chrome 119 | 2023-11-19 |
|
||||
| Safari 17.1 | 2023-11-19 |
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Live 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() {
|
||||
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:
|
||||
|
||||
```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 });
|
||||
```
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested using the standalone script in the following environments:
|
||||
|
||||
| Browser | Version | Date |
|
||||
|:------------|---------|:-----------|
|
||||
| Chrome 119 | `1.6.2` | 2023-11-19 |
|
||||
| Safari 17.1 | `1.6.2` | 2023-11-19 |
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Live 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.
|
||||
|
||||
:::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
|
||||
|
||||
[`superagent`](https://github.com/visionmedia/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);
|
||||
```
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested using the standalone script in the following environments:
|
||||
|
||||
| Browser | Version | Date |
|
||||
|:------------|---------|:-----------|
|
||||
| Chrome 119 | `8.1.2` | 2023-11-19 |
|
||||
| Safari 17.1 | `8.1.2` | 2023-11-19 |
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Live 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.
|
||||
|
||||
:::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
|
||||
|
||||
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`
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
|
||||
This demo uses `fetch` to upload data to <https://s2c.sheetjs.com>. It will parse
|
||||
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>
|
||||
|
||||
|
||||
## 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)
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Sheets in ExpressJS
|
||||
sidebar_label: ExpressJS
|
||||
pagination_prev: demos/net/network
|
||||
pagination_prev: demos/net/network/index
|
||||
pagination_next: demos/net/email/index
|
||||
---
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Sheets in Drash
|
||||
sidebar_label: Drash
|
||||
pagination_prev: demos/net/network
|
||||
pagination_prev: demos/net/network/index
|
||||
pagination_next: demos/net/email/index
|
||||
---
|
||||
|
2
docz/docs/03-demos/03-net/02-server/09-elysia.md → docz/docs/03-demos/03-net/03-server/09-elysia.md
2
docz/docs/03-demos/03-net/02-server/09-elysia.md → docz/docs/03-demos/03-net/03-server/09-elysia.md
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Sheets in Elysia
|
||||
sidebar_label: ElysiaJS
|
||||
pagination_prev: demos/net/network
|
||||
pagination_prev: demos/net/network/index
|
||||
pagination_next: demos/net/email/index
|
||||
---
|
||||
|
2
docz/docs/03-demos/03-net/02-server/11-nestjs.md → docz/docs/03-demos/03-net/03-server/11-nestjs.md
2
docz/docs/03-demos/03-net/02-server/11-nestjs.md → docz/docs/03-demos/03-net/03-server/11-nestjs.md
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Sheets in NestJS
|
||||
sidebar_label: NestJS
|
||||
pagination_prev: demos/net/network
|
||||
pagination_prev: demos/net/network/index
|
||||
pagination_next: demos/net/email/index
|
||||
---
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Sheets in FastifyJS
|
||||
sidebar_label: FastifyJS
|
||||
pagination_prev: demos/net/network
|
||||
pagination_prev: demos/net/network/index
|
||||
pagination_next: demos/net/email/index
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"label": "HTTP Server Processing",
|
||||
"collapsed": false,
|
||||
"position": 2
|
||||
"position": 3
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: HTTP Server Processing
|
||||
pagination_prev: demos/net/network
|
||||
pagination_prev: demos/net/upload/index
|
||||
pagination_next: demos/net/email/index
|
||||
---
|
||||
|
||||
@ -10,6 +10,15 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
Server-Side JS platforms like NodeJS and Deno have built-in APIs for listening
|
||||
on network interfaces. They provide wrappers for requests and responses.
|
||||
|
||||
:::info pass
|
||||
|
||||
This demo focuses on HTTP servers. Other demos cover other HTTP use cases:
|
||||
|
||||
- ["HTTP Downloads"](/docs/demos/net/network) covers downloading files
|
||||
- ["HTTP Uploads"](/docs/demos/net/upload) covers uploading files
|
||||
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
#### Parsing Files in POST Requests
|
Loading…
Reference in New Issue
Block a user