Use event notification to summarize PDF files on upload
In this tutorial, you will learn how to use event notifications to process a PDF file when it is uploaded to an R2 bucket. You will use Workers AI to summarize the PDF and store the summary as a text file in the same bucket.
To continue, you will need:
- A Cloudflare account ↗ with access to R2.
- Have an existing R2 bucket. Refer to Get started tutorial for R2.
- Install
Node.js
↗.
Node.js version manager
Use a Node version manager like Volta ↗ or
nvm ↗ to avoid permission issues and change
Node.js versions. Wrangler, discussed
later in this guide, requires a Node version of 16.17.0
or later.
You will create a new Worker project that will use Static Assets to serve the front-end of your application. A user can upload a PDF file using this front-end, which will then be processed by your Worker.
Create a new Worker project by running the following commands:
npm create cloudflare@latest -- pdf-summarizer
pnpm create cloudflare@latest pdf-summarizer
yarn create cloudflare pdf-summarizer
For setup, select the following options:
- For What would you like to start with?, choose
Hello World Starter
. - For Which template would you like to use?, choose
Worker only
. - For Which language do you want to use?, choose
TypeScript
. - For Do you want to use git for version control?, choose
Yes
. - For Do you want to deploy your application?, choose
No
(we will be making some changes before deploying).
Navigate to the pdf-summarizer
directory:
cd pdf-summarizer
Using Static Assets, you can serve the front-end of your application from your Worker. To use Static Assets, you need to add the required bindings to your Wrangler file.
{ "assets": { "directory": "public" }}
[assets]directory = "public"
Next, create a public
directory and add an index.html
file. The index.html
file should contain the following HTML code:
Select to view the HTML code
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>PDF Summarizer</title> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; min-height: 100vh; margin: 0; background-color: #fefefe; } .content { flex: 1; display: flex; justify-content: center; align-items: center; } .upload-container { background-color: #f0f0f0; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .upload-button { background-color: #4caf50; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } .upload-button:hover { background-color: #45a049; } footer { background-color: #f0f0f0; color: white; text-align: center; padding: 10px; width: 100%; } footer a { color: #333; text-decoration: none; margin: 0 10px; } footer a:hover { text-decoration: underline; } </style> </head> <body> <div class="content"> <div class="upload-container"> <h2>Upload PDF File</h2> <form id="uploadForm" onsubmit="return handleSubmit(event)"> <input type="file" id="pdfFile" name="pdfFile" accept=".pdf" required /> <button type="submit" id="uploadButton" class="upload-button"> Upload </button> </form> </div> </div>
<footer> <a href="https://developers.cloudflare.com/r2/buckets/event-notifications/" target="_blank" >R2 Event Notification</a > <a href="https://developers.cloudflare.com/queues/get-started/#3-create-a-queue" target="_blank" >Cloudflare Queues</a > <a href="https://developers.cloudflare.com/workers-ai/" target="_blank" >Workers AI</a > <a href="https://github.com/harshil1712/pdf-summarizer-r2-event-notification" target="_blank" >GitHub Repo</a > </footer>
<script> handleSubmit = async (event) => { event.preventDefault();
// Disable the upload button and show a loading message const uploadButton = document.getElementById("uploadButton"); uploadButton.disabled = true; uploadButton.textContent = "Uploading...";
// get form data const formData = new FormData(event.target); const file = formData.get("pdfFile");
if (file) { // call /api/upload endpoint and send the file await fetch("/api/upload", { method: "POST", body: formData, });
event.target.reset(); } else { console.log("No file selected"); } uploadButton.disabled = false; uploadButton.textContent = "Upload"; }; </script> </body></html>