INTEGRITY Документация

Использование уведомлений о событиях для создания сводки PDF-файлов при загрузке

В этом руководстве вы узнаете, как использовать уведомления о событиях чтобы обрабатывать PDF-файл при его загрузке в бакет R2. Вы будете использовать Workers AI , чтобы создать краткое содержание PDF-файла и сохранить его в виде текстового файла в том же бакете.

Предварительные требования

Чтобы продолжить, вам потребуется:

менеджер версий Node.js

Используйте менеджер версий Node, например Volta или nvm чтобы избежать проблем с правами доступа и менять версии Node.js. Wrangler, рассмотренная далее в этом руководстве, требует версии Node 16.17.0 или более поздней версии.

1. Создать новый проект

Вы создадите новый проект Worker, который будет использовать Static Assets чтобы обслуживать фронтенд вашего приложения. Пользователь может загрузить PDF-файл через этот фронтенд, который затем будет обработан вашим Worker.

Создайте новый проект Worker, выполнив следующие команды:

npm create cloudflare@latest -- pdf-summarizer

Для настройки выберите следующие параметры:

Перейдите в pdf-summarizer каталог:

cd pdf-summarizer

2. Создать фронтенд

С помощью Static Assets вы можете обслуживать фронтенд своего приложения прямо из Worker. Чтобы использовать Static Assets, добавьте необходимые привязки в файл Wrangler.

{
	"assets": {
		"directory": "public"
	}
}
[assets]
directory = "public"

Далее создайте public каталог и добавьте index.html файл. index.html файл должен содержать следующий HTML-код:

Выберите, чтобы просмотреть код HTML

<!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>

Чтобы просмотреть интерфейс приложения, выполните следующую команду и перейдите по URL-адресу, отображенному в терминале:

npm run dev
 ⛅️ wrangler 3.80.2
-------------------

⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:8787
╭───────────────────────────╮
│  [b] open a browser       │
│  [d] open devtools        │
│  [l] turn off local mode  │
│  [c] clear console        │
│  [x] to exit              │
╰───────────────────────────╯

Открыв этот URL в браузере, вы увидите форму загрузки файла. Если попробовать загрузить файл, он не будет отправлен на сервер: это связано с тем, что фронтенд ещё не подключён к бэкенду. На следующем шаге вы обновите Worker, который будет обрабатывать загрузку файла.

3. Обработать загрузку файлов

Чтобы обработать загрузку файла, сначала нужно добавить привязку R2. В файле Wrangler добавьте следующий код:

{
	"r2_buckets": [
		{
			"binding": "MY_BUCKET",
			"bucket_name": "<R2_BUCKET_NAME>"
		}
	]
}
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<R2_BUCKET_NAME>"

Замените <R2_BUCKET_NAME> именем вашего бакета R2.

Далее обновите src/index.ts файл. src/index.ts файл должен содержать следующий код:

src/index.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		// Get the pathname from the request
		const pathname = new URL(request.url).pathname;

		if (pathname === "/api/upload" && request.method === "POST") {
			// Get the file from the request
			const formData = await request.formData();
			const file = formData.get("pdfFile") as File;

			// Upload the file to Cloudflare R2
			const upload = await env.MY_BUCKET.put(file.name, file);
			return new Response("File uploaded successfully", { status: 200 });
		}

		return new Response("incorrect route", { status: 404 });
	},
} satisfies ExportedHandler<Env>;

Приведённый выше код выполняет следующее:

Поскольку код Worker написан на TypeScript, выполните следующую команду, чтобы добавить необходимые определения типов. Это не обязательно, но поможет избежать ошибок.

npm run cf-typegen

Вы можете перезапустить сервер разработки, чтобы проверить изменения:

npm run dev

4. Создать очередь

Уведомления о событиях фиксируют изменения данных в вашем бакете R2. Вам нужно будет создать новую очередь pdf-summarize чтобы получать уведомления:

npx wrangler queues create pdf-summarizer

Добавьте привязку в файл Wrangler:

{
	"queues": {
		"consumers": [
			{
				"queue": "pdf-summarizer"
			}
		]
	}
}
[[queues.consumers]]
queue = "pdf-summarizer"

5. Обработка уведомлений о событиях

Теперь, когда у вас есть очередь для получения уведомлений о событиях, нужно обновить Worker, чтобы он их обрабатывал. Добавьте обработчик Queue, который будет извлекать текстовое содержимое из PDF, передавать его в Workers AI для формирования сводки и сохранять результат в бакете R2.

Обновите src/index.ts файл, чтобы добавить обработчик Queue:

src/index.ts
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>;

Приведённый выше код выполняет следующее:

На данный момент queue обработчик пока ничего не делает. На следующих шагах вы обновите queue обработчик, чтобы он извлекал текстовое содержимое из PDF, использовал Workers AI для создания краткого содержания и затем добавлял его в бакет.

6. Извлечь текстовое содержимое из PDF

Чтобы извлечь текстовое содержимое из PDF, Worker будет использовать unpdf библиотека. unpdf библиотека предоставляет инструменты для работы с файлами PDF.

Установите unpdf библиотеку установите с помощью следующей команды:

npm i unpdf

Обновите src/index.ts файл, чтобы импортировать необходимые модули из unpdf библиотека:

src/index.ts
import { extractText, getDocumentProxy } from "unpdf";

Далее обновите queue обработчик, чтобы он извлекал текстовое содержимое из PDF:

src/index.ts
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)}...`);
    }
}

Приведённый выше код выполняет следующее:

7. Использовать Workers AI для составления сводки содержимого

Чтобы использовать Workers AI, нужно добавить привязку Workers AI в файл Wrangler. Файл Wrangler должен содержать следующий код:

{
	"ai": {
		"binding": "AI"
	}
}
[ai]
binding = "AI"

Выполните следующую команду, чтобы добавить определение типа AI:

npm run cf-typegen

Обновите src/index.ts файл, чтобы использовать Workers AI для создания сводки содержимого:

src/index.ts
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)}...`);
  }
}

queue обработчик теперь использует Workers AI для создания краткого содержания.

8. Добавить сводку в бакет R2

Теперь, когда у вас есть сводка, добавьте её в бакет R2. Обновите src/index.ts файл, чтобы добавить сводку в bucket R2:

src/index.ts
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}`);
  }
}

Обработчик очереди теперь добавляет сводку в бакет R2 в виде текстового файла.

9. Включить уведомления о событиях

Ваш queue обработчик готов обрабатывать входящие сообщения уведомлений о событиях. Теперь нужно включить уведомления о событиях с помощью wrangler r2 bucket notification create команда для вашего бакета. Следующая команда создает уведомление о событии для object-create тип события для pdf суффикс:

npx wrangler r2 bucket notification create <R2_BUCKET_NAME> --event-type object-create --queue pdf-summarizer --suffix "pdf"

Замените <R2_BUCKET_NAME> именем вашего бакета R2.

Уведомление о событии создается для pdf суффикс. Когда новый файл с pdf суффиксом загружается в бакет R2, pdf-summarizer очередь запускается.

10. Развернуть Worker

Чтобы развернуть Worker, выполните wrangler deploy команда:

npx wrangler deploy

В выводе wrangler deploy команду и скопируйте URL. Это URL вашего развёрнутого приложения.

11. Тестирование

Чтобы протестировать приложение, перейдите по URL-адресу развернутого приложения и загрузите PDF-файл. Либо вы можете использовать Панель управления Cloudflare , чтобы загрузить PDF-файл.

Чтобы просмотреть журналы, можно использовать wrangler tail команда.

npx wrangler tail

Логи появятся в вашем терминале. Их также можно посмотреть в панели управления Cloudflare, в разделе Workers Logs.

Если вы проверите свой бакет R2, то увидите файл сводки.

Заключение

В этом руководстве вы узнали, как использовать уведомления о событиях R2 для обработки объекта при загрузке. Вы создали приложение для загрузки PDF-файла и Worker-обработчик, который формирует сводку по PDF-файлу. Вы также узнали, как использовать Workers AI для создания сводки содержимого PDF-файла и загрузки этой сводки в бакет R2.

Тот же подход можно использовать для обработки других типов файлов, например изображений, видео и аудио. Он также подходит для обработки других типов событий, например удаления или обновления объекта.

Если вы хотите посмотреть код этого руководства, вы найдёте его на GitHub.