Use event notification to summarize PDF ·续
[[queues.consumers]]
queue = "pdf-summarizer"
5. Handle event notifications
Now that you have a queue to receive event notifications, you need to update the Worker to handle the event notifications. You will need to add a Queue handler that will extract the textual content from the PDF, use Workers AI to summarize the content, and then save it in the R2 bucket.
Update the src/index.ts file to add the Queue handler:
src/index.tsts
export default {
async fetch(request, env, ctx): Promise<Response> {
// No changes in the fetch handler
},
async queue(batch, env) {
for (let message of batch.messages) {
console.log(`Processing the file: ${message.body.object.key}`);
}
},
} satisfies ExportedHandler<Env>;
The above code does the following:
- The
queuehandler is called when a new message is added to the queue. It loops through the messages in the batch and logs the name of the file.
For now the queue handler is not doing anything. In the next steps, you will update the queue handler to extract the textual content from the PDF, use Workers AI to summarize the content, and then add it to the bucket.
6. Extract the textual content from the PDF
To extract the textual content from the PDF, the Worker will use the unpdf ↗︎ library. The unpdf library provides utilities to work with PDF files.
Install the unpdf library by running the following command:
npmyarnpnpmbun
npm i unpdf
yarn add unpdf
pnpm add unpdf
bun add unpdf
Update the src/index.ts file to import the required modules from the unpdf library:
src/index.tsts
import { extractText, getDocumentProxy } from "unpdf";
Next, update the queue handler to extract the textual content from the PDF:
src/index.tsts
async queue(batch, env) {
for(let message of batch.messages) {
console.log(`Processing file: ${message.body.object.key}`);
// Get the file from the R2 bucket
const file = await env.MY_BUCKET.get(message.body.object.key);
if (!file) {
console.error(`File not found: ${message.body.object.key}`);
continue;
}
// Extract the textual content from the PDF
const buffer = await file.arrayBuffer();
const document = await getDocumentProxy(new Uint8Array(buffer));
const {text} = await extractText(document, {mergePages: true});
console.log(`Extracted text: ${text.substring(0, 100)}...`);
}
}
The above code does the following:
- The
queuehandler gets the file from the R2 bucket. - The
queuehandler extracts the textual content from the PDF using theunpdflibrary. - The
queuehandler logs the textual content.
7. Use Workers AI to summarize the content
To use Workers AI, you will need to add the Workers AI binding to the Wrangler file. The Wrangler file should contain the following code:
{
"ai": {
"binding": "AI"
}
}
[ai]
binding = "AI"
Execute the following command to add the AI type definition:
npm run cf-typegen
Update the src/index.ts file to use Workers AI to summarize the content:
src/index.tsts
async queue(batch, env) {
for(let message of batch.messages) {
// Extract the textual content from the PDF
const {text} = await extractText(document, {mergePages: true});
console.log(`Extracted text: ${text.substring(0, 100)}...`);
// Use Workers AI to summarize the content
const result: AiSummarizationOutput = await env.AI.run(
"@cf/facebook/bart-large-cnn",
{
input_text: text,
}
);
const summary = result.summary;
console.log(`Summary: ${summary.substring(0, 100)}...`);
}
}
The queue handler now uses Workers AI to summarize the content.
8. Add the summary to the R2 bucket
Now that you have the summary, you need to add it to the R2 bucket. Update the src/index.ts file to add the summary to the R2 bucket:
src/index.tsts
async queue(batch, env) {
for(let message of batch.messages) {
// Extract the textual content from the PDF
// ...
// Use Workers AI to summarize the content
// ...
// Add the summary to the R2 bucket
const upload = await env.MY_BUCKET.put(`${message.body.object.key}-summary.txt`, summary, {
httpMetadata: {
contentType: 'text/plain',
},
});
console.log(`Summary added to the R2 bucket: ${upload.key}`);
}
}
The queue handler now adds the summary to the R2 bucket as a text file.
9. Enable event notifications
Your queue handler is ready to handle incoming event notification messages. You need to enable event notifications with the wrangler r2 bucket notification create command for your bucket. The following command creates an event notification for the object-create event type for the pdf suffix:
npx wrangler r2 bucket notification create <R2_BUCKET_NAME> --event-type object-create --queue pdf-summarizer --suffix "pdf"
Replace <R2_BUCKET_NAME> with the name of your R2 bucket.
An event notification is created for the pdf suffix. When a new file with the pdf suffix is uploaded to the R2 bucket, the pdf-summarizer queue is triggered.
10. Deploy your Worker
To deploy your Worker, run the wrangler deploy command:
npx wrangler deploy
In the output of the wrangler deploy command, copy the URL. This is the URL of your deployed application.
11. Test
To test the application, navigate to the URL of your deployed application and upload a PDF file. Alternatively, you can use the Cloudflare dashboard ↗︎ to upload a PDF file.
To view the logs, you can use the wrangler tail command.
npx wrangler tail
You will see the logs in your terminal. You can also navigate to the Cloudflare dashboard and view the logs in the Workers Logs section.
If you check your R2 bucket, you will see the summary file.
Conclusion
In this tutorial, you learned how to use R2 event notifications to process an object on upload. You created an application to upload a PDF file, and created a consumer Worker that creates a summary of the PDF file. You also learned how to use Workers AI to summarize the content of the PDF file, and upload the summary to the R2 bucket.
You can use the same approach to process other types of files, such as images, videos, and audio files. You can also use the same approach to process other types of events, such as object deletion, and object update.
If you want to view the code for this tutorial, you can find it on GitHub ↗︎.
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/r2/tutorials/summarize-pdf/#page","headline":"Use event notification to summarize PDF files on upload","description":"Use event notification to summarize PDF files on upload. Use Workers AI to summarize the PDF and store the summary as a text file.","url":"https://developers.cloudflare.com/r2/tutorials/summarize-pdf/","inLanguage":"en","image":"https://developers.cloudflare.com/r2/tutorials/summarize-pdf/og.png?v=2aac5fec5ecac859","dateModified":"2026-10-12","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["TypeScript"]}
description: This example provides a step-by-step guide on using event notifications to capture and store R2 upload logs in a separate bucket. title: Log and store upload events in R2 with event notifications image: https://developers.cloudflare.com/r2/tutorials/upload-logs-event-notifications/og.png?v=271a31c0e32a314a
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/r2/llms.txt
Use this file to discover all available pages before exploring further.
Docs