PDF API için TypeScript SDK: İlk Çağrıya Beş Dakika ve Size Bıraktıkları
@pdf123/sdk’yi TypeScript’ten kullanarak dosyaları birleştirin, filigran ekleyin, dosya bilgisini okuyun ve birkaç aracı tek bir istekte zincirleyin. Yanlış yazılmış bir araç adını ya da parametreyi hiçbir şey yüklenmeden önce yakalar; sunucu reddettiğinde yanıt bir neden ve bir ipucu taşır, ancak yeniden denemeler, iptal ve toplu işteki kısmi başarısızlıklar size aittir.

PDF API’yi Node’dan çağırdığınızda @pdf123/sdk yazılım geliştirme kiti (SDK), yanlış yazılmış bir araç adını ya da parametreyi herhangi bir dosya yüklenmeden önce yakalar. Yeniden denemez, sizin yerinize iptal etmez ve sonuçları akış olarak vermez. new Pdf123Client() varsayılan olarak anonim biçimde https://pdf123.xyz adresine bağlanır; dosyalarınız oraya yüklenir ve orada işlenir, çünkü yerel bir motor yoktur.
Klasördeki iki PDF birleştirmek için yeter
Node 20.3 veya daha yenisi ya da Bun gerekir. Paket bir ES modülüdür: kodu bir .mjs dosyasına koyun ya da önce npm pkg set type=module çalıştırın. a.pdf ve b.pdf dosyalarını geçerli dizine koyun.
npm install @pdf123/sdk
// merge.mjs
import { Pdf123Client } from "@pdf123/sdk";
import { readFileInput, saveResult } from "@pdf123/sdk/node";
const client = new Pdf123Client();
const merged = await client.run("merge", {
input: [await readFileInput("a.pdf"), await readFileInput("b.pdf")],
});
console.log(await saveResult(merged, { output: "merged.pdf" }));
node merge.mjs çalıştıktan sonra terminal, verdiğiniz çıktı yolunu, yani merged.pdf yazdırır ve dosya geçerli dizindedir. readFileInput ve saveResult, @pdf123/sdk/node içinde bulunur. Kök giriş noktası yalnızca fetch’e dayanır ve girdileri düz { name, data } olarak alır; bu yüzden dosya sistemi olmayan bir ortam da aynı istemciyi kullanabilir. Bir sonuç { data, contentType, filename, json } biçimindedir; data bütün bir Uint8Array’dir ve Buffer.from(result.data) size bir Buffer verir.
PDF birleştir araçlardan yalnızca biridir.
Dosyalar data içinde, raporlar json içinde döner
Her araç client.run(toolName, { input, params }) biçimindedir. Aşağıdaki kod, önceki bölümdeki merge.mjs dosyasının devamıdır; client ve saveResult zaten kapsamdadır. Sonucu nereden okuyacağınız, getTool’dan gelen returns alanına bağlıdır; bu alan "file" ya da "json" olur: birincisi için data, ikincisi için json kullanın.
import { getTool } from "@pdf123/sdk";
import { readFileInput, saveResult } from "@pdf123/sdk/node";
// client comes from merge.mjs in the previous section
const marked = await client.run("watermark", {
input: await readFileInput("a.pdf"),
params: { watermarkText: "DRAFT", fontSize: 40 },
});
console.log(await saveResult(marked, { output: "marked.pdf" }));
const info = await client.run("get-info", { input: await readFileInput("a.pdf") });
console.log(info.json.FileSize, info.json.Encrypted);
console.log(getTool("get-info")?.returns); // "json"
İlk blok filigranlı dosyayı marked.pdf içine yazar; ikincisinde rapor info.json’dır. Alan adlarını, varsayılanları ya da izin verilen değerleri ezberlemeniz gerekmez: getTool("watermark")?.fields o kataloğun kendisidir ve komut satırındaki pdfx describe watermark da aynı kataloğu okur. TOOLS 95 aracın tamamını tutar. Tam başvuru geliştirici sayfasındaki SDK kılavuzunda yer alır.
Önce birleştirip, sonra filigran ekleyip, sonra sıkıştırmak için pipeline kullanabilir ya da art arda üç run çağrısı yapabilirsiniz; hangisi olacağı, ara dosyaları isteyip istemediğinize bağlıdır. Bu da yukarıdaki client’ın devamıdır. pipeline üç adımı tek bir isteğe katlar, ara sonuçlar sunucuda kalır ve çağıran yalnızca son adımı alır; aşağıdaki kod onu out.pdf içine yazar. Her adımın dosyasını istiyorsanız aşamaları ayrı ayrı çağırın.
const result = await client.pipeline(
[{ tool: "merge" }, { tool: "watermark", params: { watermarkText: "DRAFT" } }, { tool: "compress" }],
[await readFileInput("a.pdf"), await readFileInput("b.pdf")],
);
console.log(await saveResult(result, { output: "out.pdf" }));
Bir pipeline en fazla 8 adım içerir. 9. adım HTTP 400: at most 8 pipeline steps allowed hatasını alır.
Anonim, anahtarla ya da kendi sunucunuza yönlendirilmiş
PDFX_API_BASE ayarladığınız hâlde hâlâ https://pdf123.xyz adresine gidiyorsanız, bunun nedeni new Pdf123Client()’ın ortam değişkenlerini okumamasıdır; yalnızca kendi yapıcı seçeneklerine bakar.
Anonim çağrılar için bu yapıcıyı olduğu gibi kullanın. Anahtarla çağırmak için new Pdf123Client({ apiKey: process.env.PDFX_API_KEY }) yazın; istek başlığı X-API-KEY’dir.
Kendi sunucunuza yönlendirmek için @pdf123/sdk/node içindeki clientFromEnv() işlevini kullanın. PDFX_API_BASE ve PDFX_API_KEY değişkenlerini okur. Doğrudan new Pdf123Client({ baseUrl: "http://localhost:8080" }) de yazabilirsiniz. Adrese ulaşılamıyorsa çağrı başarısız olur; çevrimdışı mod yoktur. Dosyalar kendi ağınızda kaldığında neyin kazanıldığı ve bunun neye mal olduğu Kendi sunucunuzda barındırmak size gerçekte ne kazandırır (ve neye mal olur) yazısında anlatılır.
Yanlış bir parametre yüklemeden önce yakalanır
Bu olmasaydı dosya önce yüklenir ve yanlış yazılmış bir alan adı ancak sunucudan gelen bir 400 olarak ortaya çıkardı. Her aracın parametre türleri katalogdan üretilir; bu yüzden üç yaygın hata tsc aşamasında düşer:
| Yazdığınız | Derleyici hatası (alıntı) |
|---|---|
client.run("rotat", { input }) |
Argument of type '"rotat"' is not assignable to parameter of type 'ToolId' |
params: { watermarkTxt: "DRAFT" } |
Object literal may only specify known properties, but 'watermarkTxt' does not exist, ending with Did you mean to write 'watermarkText'? |
params: { angle: 45 } (rotate yalnızca 90, 180, 270 kabul eder) |
Type '45' is not assignable to type …, followed by the allowed values |
{ angle: 90 } ya da { watermarkText: "DRAFT", fontSize: 30 } gibi doğru çağrılar derlenir. Sayısal alanlar hem sayı hem dize kabul eder; yani fontSize: 30 ile fontSize: "30" eşdeğerdir. TypeScript kullanmayan bir proje aynı hataları çalışma zamanında alır ve istek hiç gönderilmez: üçüncü durum Field "angle" of "rotate" must be one of: 90, 180, 270 verir, yanlış yazılmış bir araç adı ise unknown_tool verir ve benzer adlar iletide listelenir.
Sunucu reddettiğinde reason üzerinden dallanın
Sunucu bir isteği reddettiğinde SDK, status, code, reason ve problem.hint taşıyan bir Pdf123Error fırlatır. Bir code’un birden çok reason değeri olabilir; bu yüzden önce reason’a bakın, bulamazsanız code’a dönün. Aynı girdiyle yerelde çalıştırılan üç yaygın hata şöyle görünür:
| Girdi | status | code | reason | hint (özgün metin İngilizcedir) |
|---|---|---|---|---|
| Şifreli PDF, parola verilmedi | 400 | bad_request |
password_required |
Provide the document password, or unlock the PDF first |
| Yanlış parola | 400 | bad_request |
wrong_password |
Check the password and try again |
| PDF değil ya da hasarlı dosya | 400 | invalid_document |
invalid_pdf |
Upload a valid, undamaged PDF; you can try repairing it first |
import { Pdf123Client, Pdf123Error } from "@pdf123/sdk";
import { readFileInput } from "@pdf123/sdk/node";
const client = new Pdf123Client();
const input = await readFileInput("locked.pdf");
try {
await client.run("compress", { input });
} catch (error) {
if (!(error instanceof Pdf123Error)) throw error;
console.error(error.status, error.code, error.reason, error.problem?.hint);
if (error.reason === "password_required") {
await client.run("compress", { input, password: "secret" });
}
}
Parolayı biliyorsanız tek bir dosya için password verin; kilidi açma ve hedef araç aynı istekte gerçekleşir. Hasarlı bir dosya için önce PDF onar aracını deneyin.
"Sonuç yok" durumunun ayırt edilmesi gerekir. PDF'den CSV'ye PDF’de tablo bulamazsa sunucu 204 döndürür ve SDK code: "no_content" fırlatır; nedeni Boş tablo dışa aktarma (204): PDF’nizde büyük olasılıkla sütun yok yazısında anlatılır. Koşullu filtre araçları yanlış çıkan bir koşulu normal bir sonuç sayar: hata fırlatmazlar, boş bir data ile birlikte matched: false döndürürler.
Yeniden denemeler, bellek ve iptal çağıranın işidir
Ağ hataları ve 5xx yanıtları olduğu gibi fırlatılır; SDK kendi kendine asla yeniden denemez. Durumu değiştiren bir istek için kendi idempotencyKey değerinizi verin: aynı anahtarla yeniden göndermek, yeniden işlemek yerine ilk sonucu döndürür; mekanizma ve sınırlar Idempotency-Key: PDF işleri için güvenli yeniden denemeler yazısındadır. Sonuçlar belleğe bütün olarak okunur, akış yoktur. Hem girdi hem çıktı büyükse, ikisinin aynı anda kapladığı belleği hesaba katın.
İptal ile zaman aşımı iki ayrı code değeridir ve tek bir çağrı yalnızca önce gerçekleşeni bildirir. Aşağıdaki örnek ikisini iki ayrı çağrıda dener; böylece her iki dal da gerçekten çalışabilir:
import { Pdf123Client, Pdf123Error } from "@pdf123/sdk";
import { readFileInput } from "@pdf123/sdk/node";
const client = new Pdf123Client();
const input = await readFileInput("a.pdf");
const controller = new AbortController();
setTimeout(() => controller.abort(), 10_000);
try {
await client.run("compress", { input, signal: controller.signal });
} catch (error) {
if (error instanceof Pdf123Error && error.code === "cancelled") { /* siz iptal ettiniz */ }
}
try {
await client.run("compress", { input, timeoutMs: 60_000 });
} catch (error) {
if (error instanceof Pdf123Error && error.code === "timeout") { /* timeoutMs aşıldı; bu sefer signal yok */ }
}
İptal sinyali (AbortSignal) tetiklenir tetiklenmez istek code: "cancelled" ile reddedilir; zaman aşımı aşılırsa code: "timeout" gelir. Her isteğin varsayılan zaman aşımı 5 dakikadır; bunu istemciyi oluştururken değiştirebilir ya da çağrı başına timeoutMs ile geçersiz kılabilirsiniz. Parçalı yüklemede her istek bu zaman aşımını kendi başına taşır. İptal yalnızca bu bağlantıyı kapatır; sunucunun işlemeyi bırakacağının garantisi yoktur.
Bir dosya başarısız olur, gerisi sürer ve geri çağrılar tamamlanma sırasıyla gelir
Tek dosyalı bir araca bir girdi grubu vermek için runBatch kullanın. Bir dosya başarısız olursa diğerleri sürer. onResult her dosya biter bitmez çağrılır; dolayısıyla tamamlanma sırasıyla çalışır ve index dosyanın girdi dizisindeki konumudur; döndürülen dizi her zaman girdi sırasındadır. Baytları diske bu geri çağrının içinde yazın: retainData: false, geri çağrı döner dönmez data’yı boşaltır, yani burada saveResult yapmadığınız sonuç kaybolur. Çalışma yarıda kesilirse, yazılmış dosyalar kalır.
Klasörde üç sağlam PDF olduğunu varsayın: a.pdf, b.pdf ve şifreli locked.pdf (parola secret); ayrıca içinde yalnızca birkaç yazılmış karakter bulunan bozuk bir broken.pdf:
import { Pdf123Client } from "@pdf123/sdk";
import { fileSource, saveResult } from "@pdf123/sdk/node";
const client = new Pdf123Client();
const results = await client.runBatch("compress", [
fileSource("a.pdf"), fileSource("broken.pdf"), fileSource("b.pdf"), fileSource("locked.pdf"),
], {
concurrency: 2,
passwordFor: (file) => (file.name === "locked.pdf" ? "secret" : undefined),
onResult: async (entry, index) => {
console.log(index, entry.input.name, entry.ok ? "ok" : entry.error.reason);
if (entry.ok) await saveResult(entry.result, { output: "out/" });
},
retainData: false,
});
Varsayılan olarak aynı anda iki dosya işlenir; bunu concurrency ile değiştirebilirsiniz. fileSource(path) dosyayı diskten yalnızca sırası geldiğinde okur; böylece büyük dosyalardan oluşan büyük bir grup hiçbir zaman bir arada belleğe yüklenmez. passwordFor, kilitli ve kilitsiz dosyaları karışık içeren bir grubun tek seferde çalışmasını sağlar. Yukarıdaki dört dosyayı yerelde çalıştırdığımızda geri çağrı şunları aldı:
1 broken.pdf invalid_pdf
0 a.pdf ok
2 b.pdf ok
3 locked.pdf ok
Tamamlanma sırası her çalıştırmada farklı olabilir; bu, yalnızca bir çalıştırmanın nasıl göründüğüdür. retainData: false, döndürülen dizideki data’yı boş yapar; başarılı dosyalar yukarıdaki saveResult ile zaten out/ içine yazılmıştı. runBatch’e idempotencyKey verdiğinizde her dosya için gerçekten gönderilen anahtar <key>:<index> olur.
Parçalı yükleme yalnızca toplam 95 MiB’nin üstünde başlar
Doğrudan bir istek gövdesi 100 MiB ile sınırlıdır ve daha büyüğü reddedilir; ayrıntılar için Büyük Bir PDF Yüklemesi Reddedildiğinde: 100 MiB İstek Gövdesi Sınırı ve Sizi Yanlış Yöne Saptıran Hata yazısına bakın. Tek bir istekteki bütün dosyaların toplamı 95 MiB’yi aştığında SDK parçalı yüklemeye geçer ve client.run çağrınız değişmez. Sunucunun tek yükleme için varsayılan üst sınırı 500 MiB’dir; kendi sunucunuzda barındırırken bunu PDFX_UPLOAD_MAX_BYTES ile ayarlayın.
Aynı işlemin curl, MCP ve komut satırıyla yazılmış hâli için Aynı işlem, dört istemci: tarayıcı, curl, MCP, pdfx yazısına bakın: o yazı dört çağrıyı yan yana koyar, bu yazı ise yalnızca SDK’yı açar. Paketin npm üzerindeki sayfası @pdf123/sdk adresindedir.