docs.sheetjs.com/docz/docs/03-demos/30-cloud/14-cloudflare.md

238 lines
8.1 KiB
Markdown
Raw Normal View History

2024-04-03 00:12:07 +00:00
---
title: Cloudflare
pagination_prev: demos/local/index
pagination_next: demos/extensions/index
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
[Cloudflare](https://www.cloudflare.com/) is a cloud services
platform which includes "Serverless
Functions" and cloud storage.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo explores two key Cloudflare offerings:
- ["Cloudflare Workers"](#cloudflare-workers) explores the serverless
computing offering. The demo creates a JavaScript function that can process
user-submitted files and generate spreadsheets.
- ["Cloudflare R2"](#cloudflare-r2) explores the cloud storage ("R2") offering. The
demo uses the NodeJS connection library to read spreadsheets from R2 and write
spreadsheets to an R2 bucket.
:::note Tested Deployments
This demo was last tested on 2024 April 02.
:::
## Cloudflare Workers
Cloudflare offers NodeJS runtimes for running JavaScript serverless functions.[^1]
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
2024-04-03 02:05:56 +00:00
required in Cloudflare Workers. Cloudflare provides a cli called C3 [^2] in order to setup your worker project and another cli called Wrangler [^3]
which can streamline development and deployment,
2024-04-03 00:12:07 +00:00
:::note pass
2024-04-03 00:16:16 +00:00
In this demo, Wrangler is used as that is Cloudflare's recommended way of developing and deploying to
Workers
2024-04-03 00:12:07 +00:00
:::
2024-04-03 04:42:25 +00:00
### Overview
Cloudflare Workers exposes a handler in src/index.(js|ts) when you create a worker project using C3 as per above,
this handler exposes a Request object which can be used to expose the formdata or json of the request to the worker
```ts
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const data = await request.formData()
// const data = await request.json() if you are receiving a json request
//...
},
};
2024-04-03 00:12:07 +00:00
```
2024-04-03 04:42:25 +00:00
### Reading Data
2024-04-03 00:12:07 +00:00
2024-04-03 04:42:25 +00:00
The SheetJS `read` method[^4] can read ArrayBuffer objects and generate SheetJS
workbook objects[^5] which can be processed with other API functions.
For example, a handler can use `sheet_to_csv`[^6] to generate CSV text:
```ts
import XLSX from "xlsx";
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
if (request.method === 'POST') {
const data = await request.formData()
// const data = await request.json() if you are doing a json request
const file = data.get('file') as File;
const buffer = await file.arrayBuffer();
const wb = XLSX.read(buffer);
const ws = wb.Sheets[wb.SheetNames[0]];
var b64 = XLSX.write(wb, { type: "base64", bookType: "xlsx" });
return new Response(XLSX.utils.sheet_to_csv(ws))
}
return new Response('Hello World!');
},
2024-04-03 00:12:07 +00:00
};
```
### Writing Data
2024-04-03 04:42:25 +00:00
```ts
import XLSX from "xlsx";
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
var wb = XLSX.read("S,h,e,e,t,J,S\n5,4,3,3,7,9,5", {type: "binary"});
var data = XLSX.write(wb, { type: "buffer", bookType: "xlsx" });
return new Response(data,{
status: 200,
headers: {
"Content-Disposition": 'attachment; filename="SheetJSCFWorker.xlsx"' //Content disposition will make the browser download the file
}
})
},
2024-04-03 00:12:07 +00:00
};
```
2024-04-03 04:42:25 +00:00
### Cloudflare Workers Demo
2024-04-03 00:12:07 +00:00
:::note pass
2024-04-03 04:42:25 +00:00
At the time of writing, the Cloudflare Workers Free Tier included an allowance of 100,000
free requests per day and 10 milliseconds of CPU time per invocation.
2024-04-03 00:12:07 +00:00
:::
2024-04-03 04:42:25 +00:00
1) If you do not have an account, create a new account[^7].
2024-04-03 00:12:07 +00:00
2024-04-03 04:56:14 +00:00
### Setting up the Project and Testing
2024-04-03 00:12:07 +00:00
2024-04-03 04:56:14 +00:00
[The Cloudflare Docs provide a simple step by step guide to setup, develop, test, build and deploy your project](https://developers.cloudflare.com/workers/get-started/guide/)
2024-04-03 00:12:07 +00:00
## Cloudflare R2
2024-04-03 05:57:36 +00:00
Due to R2's S3 compatability, the main NodeJS module for Cloudflare R2 is actually the AWS S3 SDK `@aws-sdk/client-s3`[^8].
2024-04-03 00:12:07 +00:00
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
required in NodeJS scripts.
2024-04-03 05:57:36 +00:00
:::note pass
As the time of writing, Cloudflare R2 is not 100% compatible with the S3 API, please refer to the [S3 API Compatibility section of the official Cloudflare R2 Docs](https://developers.cloudflare.com/r2/api/s3/api/) to know more about what S3 Features are and are not supported.
:::
2024-04-03 00:12:07 +00:00
### Connecting to R2
2024-04-03 05:57:36 +00:00
The `@aws-sdk/client-s3` module exports a class `S3Client` that performs the connection. The
function expects an options object that includes a region, credentials and in the case of R2 an endpoint.
this client is used to interact with R2.
2024-04-03 00:12:07 +00:00
2024-04-03 05:57:36 +00:00
```ts
import { S3Client } from "@aws-sdk/client-s3";
2024-04-03 00:12:07 +00:00
/* credentials */
2024-04-03 05:57:36 +00:00
const accessKeyId = "...", secretAccessKey = "...";
2024-04-03 00:12:07 +00:00
/* file location */
2024-04-03 05:57:36 +00:00
const Bucket = "...", Key = "pres.numbers";
2024-04-03 00:12:07 +00:00
/* connect to s3 account */
2024-04-03 05:57:36 +00:00
const Cloudflare = require('Cloudflare-sdk');
const s3 = new S3Client({
region: "REGION", //For cloudflare, if the cloudflare region is Auto then you put "auto"
credentials: {
accessKeyId,
secretAccessKey
},
endpoint: 'R2-ENDPOINT' //Note that the cloudflare dashboard will include the bucket prefix to the endpoint
//Make sure the endpoint ends with .r2.cloudflarestorage.com not .r2.cloudflarestorage.com/bucket-name
2024-04-03 00:12:07 +00:00
});
```
### Downloading Data
2024-04-03 05:57:36 +00:00
#### Fetching Files from R2
2024-04-03 00:12:07 +00:00
2024-04-03 05:57:36 +00:00
The S3 SDK's client mentioned above when instantiated does needs to be fed commands through its ```.send()``` method
to interact with R2.
2024-04-03 00:12:07 +00:00
2024-04-03 05:57:36 +00:00
```ts
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
/*
... Client instantiation code from before
...
...
*/
const command = new GetObjectCommand({
Bucket: 'bucket-name',
Key: 'key'
}) //Create the command object, we are using GetObjectCommand to fetch an item from R2
const data = await client.send(command); //Send the command
const bytes = await data.Body?.transformToByteArray(); //After receiving the item, transform it to a byte array
const wb = XLSX.read(bytes); //Use SheetJS as normal
const first_ws = wb.Sheets[wb.SheetNames[0]];
const csv = XLSX.utils.sheet_to_csv(first_ws);
2024-04-03 00:12:07 +00:00
```
### Uploading Data
2024-04-03 05:57:36 +00:00
The SheetJS `write` method[^9] with the option `type: "buffer"` will generate
NodeJS Buffers. `R2` directly accepts these Buffer objects.
2024-04-03 00:12:07 +00:00
This example creates a sample workbook object, generates XLSX file data in a
2024-04-03 05:57:36 +00:00
NodeJS Buffer, and uploads the data to R2:
Here we are using the PutObjectCommand object to upload the data written by
`write` into the R2 bucket
2024-04-03 00:12:07 +00:00
```js
2024-04-03 05:57:36 +00:00
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
/*
... Client instantiation code from before
...
...
*/
2024-04-03 00:12:07 +00:00
/* generate sample workbook */
var wb = XLSX.read("S,h,e,e,t,J,S\n5,4,3,3,7,9,5", {type: "binary"});
/* write to XLSX file in a NodeJS Buffer */
var Body = XLSX.write(wb, {type: "buffer", bookType: "xlsx"});
2024-04-03 05:57:36 +00:00
const command = new PutObjectCommand({
Bucket: 'bucket-name',
Key: 'key',
Body
})
await client.send(command);
2024-04-03 00:12:07 +00:00
```
2024-04-03 05:57:36 +00:00
### R2 Demo
2024-04-03 00:12:07 +00:00
:::note pass
2024-04-03 05:57:36 +00:00
At the time of writing, the Cloudflare Free Tier included 10GB of Cloudflare R2 with 1 million Class A operations
and 10 million Class B operations per month
2024-04-03 00:12:07 +00:00
2024-04-03 05:57:36 +00:00
Please visit the [official pricing model for R2 for more info](https://developers.cloudflare.com/r2/pricing/)
2024-04-03 00:12:07 +00:00
:::
[^1]: See ["Node.js compatibility"](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) in the Cloudflare documentation
2024-04-03 02:05:56 +00:00
[^2]: See ["Get started guide"](https://developers.cloudflare.com/workers/get-started/guide/#1-create-a-new-worker-project)
[^3]: [Wrangler documentation](https://developers.cloudflare.com/workers/wrangler/)
2024-04-03 04:42:25 +00:00
[^4]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^5]: See ["Workbook Object" in "SheetJS Data Model"](/docs/csf/book) for more details.
[^6]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
[^7]: Registering for a free account [on the Cloudflare Free Tier](https://dash.cloudflare.com/sign-up).
2024-04-03 05:57:36 +00:00
[^8]: The `@aws-sdk/client-s3` module is distributed [on the public NPM registry](https://www.npmjs.com/package/@aws-sdk/client-s3)
[^9]: See [`write` in "Writing Files"](/docs/api/write-options)
2024-04-03 00:12:07 +00:00
[^14]: Registering for a free account [on the Cloudflare Free Tier](https://Cloudflare.amazon.com/free/) requires a valid phone number and a valid credit card.