Асинхронна обробка PDF
PDF Oxide пропонує повноцінні асинхронні API у Python, C# та Node.js, тож видобування ніколи не блокує ваш подієвий цикл чи обробник HTTP-запитів. Ті самі методи PdfDocument доступні як асинхронні обгортки, що делегують роботу фоновому потоку / пулу потоків.
Python — AsyncPdfDocument
Кожен метод PdfDocument має awaitable-відповідник у AsyncPdfDocument. Кожен виклик обгортає синхронний метод за допомогою asyncio.to_thread().
Python
import asyncio
from pdf_oxide import AsyncPdfDocument
async def extract(path):
doc = await AsyncPdfDocument.open(path)
text = await doc.extract_text(0)
return text
asyncio.run(extract("report.pdf"))
Паралельний розподіл по сторінках
Python
import asyncio
from pdf_oxide import AsyncPdfDocument
async def extract_all(path):
doc = await AsyncPdfDocument.open(path)
page_count = await doc.page_count()
pages = await asyncio.gather(*[doc.extract_text(i) for i in range(page_count)])
return pages
Створення
AsyncPdf віддзеркалює клас Pdf для процесів створення:
Python
from pdf_oxide import AsyncPdf
pdf = await AsyncPdf.from_markdown("# Hello")
await pdf.save_async("out.pdf")
Конвертація Office
AsyncOfficeConverter виконує асинхронну конвертацію DOCX / XLSX / PPTX → PDF.
Python
from pdf_oxide import AsyncOfficeConverter
converter = AsyncOfficeConverter()
pdf_bytes = await converter.docx_to_pdf_bytes("input.docx")
Python без GIL (cp314t)
Модуль розширення pdf_oxide оголошує gil_used = false, що робить його безпечним для використання у cp314t (збірки Python 3.14 без GIL). Кілька потоків можуть викликати методи PdfDocument паралельно без серіалізації через GIL.
Python
from concurrent.futures import ThreadPoolExecutor
from pdf_oxide import PdfDocument
doc = PdfDocument("large.pdf")
with ThreadPoolExecutor(max_workers=8) as pool:
pages = list(pool.map(doc.extract_text, range(doc.page_count())))
C# — async Task<T> з CancellationToken
Кожен метод видобування та збереження має варіант *Async, що повертає Task<T> і приймає необов’язковий CancellationToken.
C#
using PdfOxide.Core;
using var doc = PdfDocument.Open("report.pdf");
string text = await doc.ExtractTextAsync(0);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var tasks = Enumerable.Range(0, doc.PageCount)
.Select(i => doc.ExtractTextAsync(i, cts.Token));
string[] pages = await Task.WhenAll(tasks);
Редактор
C#
using var editor = DocumentEditor.Open("form.pdf");
editor.SetFormFieldValue("name", "Jane Doe");
await editor.SaveAsync("filled.pdf");
Node.js — методи *Async
Кожен синхронний метод має асинхронного побратима — extractText → extractTextAsync, save → saveAsync тощо. Асинхронні виклики виконуються в пулі потоків libuv.
Node.js
const { PdfDocument } = require("pdf-oxide");
async function extractAll(path) {
const doc = new PdfDocument(path);
try {
const pageCount = doc.getPageCount();
const pages = await Promise.all(
Array.from({ length: pageCount }, (_, i) => doc.extractTextAsync(i))
);
return pages;
} finally {
doc.close();
}
}
Приклад обробника HTTP
Node.js
import express from "express";
import { PdfDocument } from "pdf-oxide";
const app = express();
app.post("/extract", express.raw({ type: "application/pdf", limit: "50mb" }), async (req, res) => {
const doc = PdfDocument.openFromBytes(req.body);
try {
const text = await doc.extractTextAsync(0);
res.json({ text });
} finally {
doc.close();
}
});
Модель конкурентності
| Мова | Механізм |
|---|---|
| Python | asyncio.to_thread делегує синхронний виклик стандартному виконавцю |
| Python (cp314t) | Справжній паралелізм потоків — GIL необов’язковий |
| C# | Task-based Asynchronous Pattern, делегування до ThreadPool |
| Node.js | робочі потоки libuv (Napi::AsyncWorker) |
| Go | Не потрібно — горутини викликають синхронні методи безпосередньо |
| Rust | Не надається — використовуйте tokio::task::spawn_blocking або власний виконавець |
Див. посібник з конкурентності щодо спільного використання одного PdfDocument між потоками.
Пов’язані сторінки
- Конкурентність — безпека потоків + паралельне читання
- Перші кроки з Python
- Перші кроки з Node.js
- Перші кроки з C#