Làm sao cài SDK?
Cài gói bằng trình quản lý gói của bạn. Cần Node 20.3 trở lên, Bun hoặc một bundler. Gói đã kèm kiểu TypeScript nên không cần @types/node.
npm install @pdf123/sdkbun add @pdf123/sdk và pnpm add @pdf123/sdk hoạt động tương tự.
Làm sao gộp hai PDF?
Tạo một client, chạy công cụ merge trên hai tệp rồi lưu kết quả. Khi không truyền tùy chọn nào, client gọi API công khai ở chế độ ẩn danh.
import { Pdf123Client } from "@pdf123/sdk";
import { readFileInput, saveResult } from "@pdf123/sdk/node";
const client = new Pdf123Client();
const result = await client.run("merge", {
input: [await readFileInput("a.pdf"), await readFileInput("b.pdf")],
});
const path = await saveResult(result, { output: "merged.pdf" });
console.log(path);Kết quả chứa các byte trong data, cùng contentType, filename do máy chủ trả về, và json cho những công cụ trả về báo cáo. Thao tác tương tự có trên website với tên Gộp PDF.
Nên import entry point nào?
| Entry point | Cần | Cung cấp |
|---|---|---|
@pdf123/sdk | Chỉ fetch | Pdf123Client, TOOLS, getTool, Pdf123Error và các hàm hỗ trợ danh mục |
@pdf123/sdk/node | Node hoặc Bun | readFileInput, fileSource, saveResult, checkOutput và clientFromEnv |
Hãy import từ entry gốc trong trình duyệt và edge runtime, và chỉ thêm entry node ở nơi bạn đọc hoặc ghi tệp.
Client có những phương thức nào?
| Phương thức | Chức năng |
|---|---|
run(tool, { input, params }) | Chạy một công cụ và trả về một kết quả |
runBatch(tool, inputs, options) | Chạy công cụ một tệp trên nhiều đầu vào và trả về một mục cho mỗi đầu vào |
pipeline(steps, input, options) | Chạy nhiều công cụ trong một yêu cầu |
call(target, files, fields) | Gửi yêu cầu thô tới một id công cụ, id thao tác hoặc đường dẫn /api/... |
upload(file) | Tải một tệp lên qua API tải lên theo từng phần và trả về id của nó |
Các hàm hỗ trợ danh mục là hàm thông thường: TOOLS liệt kê mọi công cụ, getTool(id) trả về các trường, giá trị mặc định và loại tệp được chấp nhận của một công cụ, còn toolGroup, toolSummary, matchesQuery và suggestTools giúp xây bộ chọn công cụ. Dòng lệnh in cùng danh mục này bằng pdfx list và pdfx describe.
Làm sao truyền tùy chọn cho một công cụ?
params có kiểu theo từng công cụ. Nó chỉ nhận các trường của công cụ đó, và các trường dạng lựa chọn chỉ nhận giá trị được phép. Trường số được kiểm tra theo giá trị nhỏ nhất và lớn nhất, còn tệp được kiểm tra theo các loại được chấp nhận, trước khi có gì được tải lên. Những giá trị mặc định mà máy chủ cần sẽ được điền sẵn.
const marked = await client.run("watermark", {
input: await readFileInput("a.pdf"),
params: { watermarkText: "DRAFT", fontSize: 40, rotation: -45 },
});
await saveResult(marked, { output: "draft.pdf" });Chuỗi rỗng nghĩa là "chưa đặt", khi đó áp dụng giá trị mặc định. Xem Thêm hình mờ để biết từng tùy chọn có tác dụng gì.
Làm sao xử lý nhiều tệp?
runBatch chạy một công cụ một tệp, chẳng hạn Nén, Xoay hoặc Bảo vệ, trên từng đầu vào với cùng tùy chọn. Mặc định chạy hai tệp cùng lúc. Một tệp lỗi không bao giờ làm dừng các tệp khác.
import { fileSource, saveResult } from "@pdf123/sdk/node";
const controller = new AbortController();
const entries = await client.runBatch("compress", [fileSource("a.pdf"), fileSource("b.pdf")], {
concurrency: 2,
signal: controller.signal,
onResult: async (entry, index) => {
if (entry.ok) await saveResult(entry.result, { output: "compressed/" });
},
});
console.log(entries.map((entry) => entry.ok));fileSource(path)là nguồn tải lười, chỉ được đọc khi một worker lấy đến, nên nhiều tệp lớn không bao giờ cùng nằm trong bộ nhớ.onResultnhận từng kết quả ngay khi nó hoàn tất. Hãy lưu kết quả tại đây, và nếu hủy ở tệp thứ 50 trong 100 tệp thì 49 tệp đầu vẫn được giữ lại. VớiretainData: false, mảng trả về không giữ các byte.- Mọi lời gọi đều nhận
timeoutMsvàsignalđể hủy. idempotencyKeytrở thành<key>:<index>cho từng tệp.
Các công cụ lọc (id bắt đầu bằng filter-) trả về matched: false thay vì ném lỗi khi điều kiện không thỏa. Trong một lô, tệp như vậy vẫn được tính là ok.
Làm sao nối các công cụ trong một yêu cầu?
pipeline gửi một danh sách bước và một hoặc nhiều đầu vào. Máy chủ chuyển đầu ra của mỗi bước làm đầu vào cho bước kế tiếp.
const piped = await client.pipeline(
[{ tool: "merge" }, { tool: "watermark", params: { watermarkText: "DRAFT" } }, { tool: "compress" }],
[await readFileInput("a.pdf"), await readFileInput("b.pdf")],
);
await saveResult(piped, { output: "out.pdf" });Pipeline nhận cùng các tùy chọn mật khẩu như run.
Làm sao xử lý PDF đã mã hóa?
Truyền password cho run để mở đầu vào đã mã hóa trước. Việc mở khóa và chạy công cụ diễn ra trong cùng một yêu cầu. Với công cụ nhận nhiều tệp, chẳng hạn Gộp, hãy truyền passwords với một mục cho mỗi đầu vào, dùng chuỗi rỗng cho tệp không có mật khẩu. Mỗi tệp được mở khóa riêng.
await client.run("compress", { input: await readFileInput("locked.pdf"), password: "secret" });
await client.run("merge", {
input: [await readFileInput("locked.pdf"), await readFileInput("open.pdf")],
passwords: ["secret", ""],
});Với một lô, passwordFor(file, index) trả về mật khẩu cho từng đầu vào. Để gỡ bảo vệ vĩnh viễn, hãy dùng công cụ Gỡ mật khẩu.
Lỗi hoạt động thế nào?
Khi thất bại, SDK ném Pdf123Error. Nó có status (là undefined khi không có phản hồi), code, reason cho nguyên nhân chi tiết như password_required, và problem chứa chi tiết lỗi từ máy chủ, trong đó có hint nếu có. Lỗi xác thực được ném ra trước khi có gì được tải lên.
import { Pdf123Error } from "@pdf123/sdk";
try {
await client.run("compress", { input: await readFileInput("locked.pdf") });
} catch (error) {
if (error instanceof Pdf123Error) {
console.error(error.status, error.code, error.reason, error.problem?.hint);
} else {
throw error;
}
}Các mã từ máy chủ được liệt kê ở trang Mã lỗi. Client tự bổ sung các mã sau:
| Mã | Ý nghĩa |
|---|---|
network_error | Yêu cầu không nhận được phản hồi |
timeout | Một yêu cầu vượt quá timeoutMs |
cancelled | signal của bạn đã hủy lời gọi |
input_unreadable | Không đọc được một đường dẫn cục bộ |
output_unwritable | Không lưu được kết quả vào đường dẫn đã cho |
output_mismatch | saveResult từ chối ghi tệp ZIP vào tên có đuôi .pdf |
unsupported_file_type | Công cụ không chấp nhận loại tệp này |
unknown_tool | Id công cụ không tồn tại; thông báo gợi ý các id gần giống |
invalid_target | call từ chối đường dẫn /api/... có đoạn .., . hoặc đoạn rỗng |
no_content | Công cụ không có gì để trả về (HTTP 204) |
saveResult không bao giờ ghi đè một tệp trong thư mục. Hãy gọi checkOutput(output, { several }) trước để biết, trước khi tải lên, liệu đường dẫn có ghi được hay không.
Cài đặt TypeScript và module nào hoạt động?
Các kiểu được phân giải với các cài đặt moduleResolution là nodenext, node16, bundler và node10 cũ hơn, kể cả subpath @pdf123/sdk/node. Gói là ES module nên import dùng được ở mọi nơi. require("@pdf123/sdk") từ CommonJS hoạt động trên Node 22.12 trở lên và không dùng được trên Node 20.
Làm sao cấu hình client?
| Tùy chọn | Biến môi trường | Mặc định |
|---|---|---|
baseUrl | PDFX_API_BASE | https://pdf123.xyz |
apiKey | PDFX_API_KEY | không có, tức ẩn danh |
timeoutMs | không có | 300000 |
new Pdf123Client() không bao giờ đọc biến môi trường. clientFromEnv() từ @pdf123/sdk/node đọc hai biến này, và tùy chọn bạn truyền vào được ưu tiên. Khóa được gửi trong header X-API-KEY; xem Xác thực.
Để dùng máy chủ của riêng bạn, hãy đặt baseUrl là địa chỉ của nó, ví dụ http://localhost:8080. Xem Tự host.
Tôi có thể dùng SDK trong trình duyệt không?
Có. Entry gốc @pdf123/sdk chỉ cần fetch và không phụ thuộc Node. Hãy tự tạo các đối tượng FileInput từ File hoặc Uint8Array, vì các hàm hỗ trợ tệp nằm trong entry node. Đừng đưa khóa API vào mã trình duyệt mà người khác có thể đọc được.
Trang liên quan
- Tổng quan cho nhà phát triển, gồm REST API và xác thực
- Dòng lệnh pdfx, được xây dựng trên SDK này
- Máy chủ MCP cho AI agent
- Swagger UI và tài liệu OpenAPI
- Các trang công cụ: Gộp, Tách, Nén, OCR, Bảo vệ
Câu hỏi thường gặp
SDK có cần khóa API không?
Không. Client tạo không kèm tùy chọn sẽ gọi API công khai ở chế độ ẩn danh. Hãy truyền apiKey để gửi header X-API-KEY.
SDK cần phiên bản Node nào?
Node 20.3 trở lên, hoặc Bun. Entry gốc chỉ cần fetch, nên cũng chạy được trong trình duyệt và bundler.
Làm sao dùng công cụ mới hơn SDK?
Hãy dùng client.call. Nó nhận một id công cụ, một id thao tác như general/merge-pdfs hoặc một đường dẫn /api/..., cùng các tệp và trường. Không có gì được kiểm tra hay điền mặc định ở phía cục bộ.
Tôi có thể tải lên tệp lớn đến mức nào?
Đầu vào có tổng dung lượng trên 95 MB sẽ tự động đi qua API tải lên theo từng phần. Body của một yêu cầu trực tiếp bị giới hạn ở 100 MiB.
Vì sao lời gọi của tôi ném lỗi với PDF không có bảng?
Các công cụ như pdf-to-csv và pdf-to-xlsx trả về không có nội dung khi PDF không có bảng nào phát hiện được. SDK ném Pdf123Error với mã no_content thay vì trả về tệp rỗng. Hãy kiểm tra mã đó nếu kết quả rỗng là chấp nhận được.