Implementasi tool pembaca file untuk AI Agent PHP: ekstraksi konten dari PDF, TXT, DOCX, CSV, dan JSON dengan keamanan path traversal protection dan batasan ukuran file.
Daftar Isi
- TL;DR — Ringkasan Tool Membaca File AI Agent PHP
- Instalasi Library Parsing File di PHP
- Implementasi FileTool Class untuk AI Agent PHP
- Bedah Mekanisme Keamanan Path Traversal & Error Handling:
- Integrasi FileTool ke dalam AI Agent PHP Loop
- Penanganan Dokumen Besar (>10MB): Direct FileTool vs Streaming Chunking RAG
- FAQ: Pertanyaan Seputar Tool Membaca File AI Agent PHP
- 1. Bagaimana cara mencegah serangan Path Traversal pada FileTool?
- 2. Mengapa teks file perlu dipotong (truncation) sebelum dikirimkan ke AI?
- 3. Library apa yang direkomendasikan untuk membaca PDF dan DOCX di PHP?
Terakhir diperbarui:
TL;DR — Ringkasan Tool Membaca File AI Agent PHP
- Proteksi Path Traversal: Gabungkan fungsi
basename()dan verifikasirealpath()terhadap direktori yang diizinkan untuk mencegah akses file sistem di luar folder upload. - Pembatasan Ukuran File: Batasi file maksimal ~10 MB untuk mencegah kehabisan memori server (*Memory Exhaustion*).
- Ekstraksi Multi-Format: Dukung format teks populer (PDF, DOCX, CSV, JSON, TXT) via library parser terisolasi.
- Token Truncation Buffer: Potong output teks pada batas karakter aman (misal: 8.000 karakter) guna mencegah lonjakan token context window LLM.
mbstring, zip (untuk DOCX), dan fileinfo wajib aktif.smalot/pdfparser dan phpoffice/phpword terpasang via autoloader../uploads) dengan hak akses baca (read permission).memory_limit PHP minimal 128 MB untuk parsing dokumen biner.Instalasi Library Parsing File di PHP
Untuk membaca dokumen biner seperti PDF dan DOCX secara native tanpa ketergantungan utility sistem operasi luar, pasang library parser standar industri melalui Composer:
composer require smalot/pdfparser phpoffice/phpword
Catatan Teknis Ekstraksi PDF (Vector Layer vs OCR):
Library smalot/pdfparser bekerja murni mengekstrak teks berbasis layer teks/vektor asli (dokumen PDF digital yang dihasilkan dari Microsoft Word, Google Docs, atau ekspor sistem). Jika file PDF berupa dokumen hasil scan foto/gambar bitmap, Anda memerlukan engine OCR eksternal seperti Tesseract OCR atau integrasi Multimodal Vision API (seperti GPT-4o Vision) untuk membaca teks di dalam gambar tersebut.
Salin struktur dependensi composer.json berikut ke root project AI Agent Anda untuk menginstal seluruh engine parsing dokumen sekaligus:
{
"name": "infokoding/ai-agent-file-tools",
"description": "Enterprise File Reader Tools (PDF, DOCX, CSV, JSON) for PHP AI Agents",
"type": "project",
"require": {
"php": ">=8.2",
"smalot/pdfparser": "^2.11",
"phpoffice/phpword": "^1.3",
"guzzlehttp/guzzle": "^7.9"
},
"autoload": {
"psr-4": {
"App\": "src/"
}
},
"config": {
"optimize-autoloader": true,
"sort-packages": true,
"allow-plugins": {}
}
}Composer Tip: Jalankan perintah composer install --optimize-autoloader untuk mempercepat waktu autoloading class parser pada lingkungan production.

Implementasi FileTool Class untuk AI Agent PHP
Berikut adalah implementasi class FileTool berbasis ToolInterface yang mengintegrasikan 4 lapis perlindungan keamanan path traversal, pemangkasan buffer token, dan multi-format document parser:
<?php
namespace App\Tools;
class FileTool implements ToolInterface
{
private string $allowedDir;
private int $maxFileSizeBytes;
private int $maxChars;
public function __construct(
string $allowedDir = './uploads',
int $maxFileSizeMB = 10,
int $maxChars = 8000
) {
$this->allowedDir = realpath($allowedDir) ?: $allowedDir;
$this->maxFileSizeBytes = $maxFileSizeMB * 1024 * 1024;
$this->maxChars = $maxChars;
}
public function getDefinition(): array
{
return [
'type' => 'function',
'function' => [
'name' => 'read_file',
'description' => 'Membaca dan mengekstrak teks isi file lokal (PDF, TXT, CSV, JSON, DOCX). Masukkan nama file yang tersimpan di server.',
'parameters' => [
'type' => 'object',
'properties' => [
'filename' => [
'type' => 'string',
'description' => 'Nama file dokumen yang ingin dibaca (misal: laporan-keuangan.pdf, data.csv).',
],
],
'required' => ['filename'],
],
],
];
}
public function execute(array $args): mixed
{
// Lapisan Keamanan 1: Sanitasi nama file dengan basename()
$filename = basename(trim($args['filename'] ?? ''));
if (empty($filename)) {
return ['status' => 'error', 'message' => 'Nama file tidak boleh kosong.'];
}
$filepath = $this->allowedDir . DIRECTORY_SEPARATOR . $filename;
// Lapisan Keamanan 2: Validasi realpath terhadap direktori yang diizinkan (Jail Check)
$realPath = realpath($filepath);
if (!$realPath || !str_starts_with($realPath, $this->allowedDir)) {
return ['status' => 'error', 'message' => 'Akses file ditolak: path berada di luar direktori yang diizinkan.'];
}
if (!file_exists($realPath) || !is_readable($realPath)) {
return ['status' => 'error', 'message' => "File '{$filename}' tidak ditemukan atau tidak dapat dibaca."];
}
// Lapisan Keamanan 3: Pembatasan ukuran file fisik
if (filesize($realPath) > $this->maxFileSizeBytes) {
$maxMB = $this->maxFileSizeBytes / 1024 / 1024;
return ['status' => 'error', 'message' => "Ukuran file melebihi batas maksimum {$maxMB}MB."];
}
$extension = strtolower(pathinfo($realPath, PATHINFO_EXTENSION));
try {
$text = match ($extension) {
'txt' => file_get_contents($realPath),
'json' => $this->readJson($realPath),
'csv' => $this->readCsv($realPath),
'pdf' => $this->readPdf($realPath),
'docx' => $this->readDocx($realPath),
default => null,
};
} catch (\Throwable $e) {
return ['status' => 'error', 'message' => 'Gagal memproses file: ' . $e->getMessage()];
}
if ($text === null) {
return ['status' => 'error', 'message' => "Ekstensi file '.{$extension}' tidak didukung."];
}
// Lapisan Keamanan 4: Pemotongan buffer token teks
$isTruncated = false;
if (strlen($text) > $this->maxChars) {
$text = substr($text, 0, $this->maxChars) . "\n...[Teks terpotong karena melebihi batas token buffer]";
$isTruncated = true;
}
return [
'status' => 'success',
'filename' => $filename,
'extension' => $extension,
'characters' => strlen($text),
'is_truncated' => $isTruncated,
'content' => $text,
];
}
private function readJson(string $path): string
{
$content = file_get_contents($path);
$data = json_decode($content, true);
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
private function readCsv(string $path): string
{
$lines = [];
if (($handle = fopen($path, 'r')) !== false) {
while (($row = fgetcsv($handle, 1000, ',')) !== false) {
$lines[] = implode(' | ', $row);
}
fclose($handle);
}
return implode("\n", $lines);
}
private function readPdf(string $path): string
{
if (!class_exists('\Smalot\PdfParser\Parser')) {
throw new \RuntimeException('Library smalot/pdfparser belum terpasang.');
}
$parser = new \Smalot\PdfParser\Parser();
$pdf = $parser->parseFile($path);
return $pdf->getText();
}
private function readDocx(string $path): string
{
if (!class_exists('\PhpOffice\PhpWord\IOFactory')) {
throw new \RuntimeException('Library phpoffice/phpword belum terpasang.');
}
$phpWord = \PhpOffice\PhpWord\IOFactory::load($path);
$sections = $phpWord->getSections();
$text = '';
foreach ($sections as $section) {
foreach ($section->getElements() as $element) {
if (method_exists($element, 'getText')) {
$text .= $element->getText() . "\n";
}
}
}
return $text;
}
}- Kontrak ToolInterface: Mengimplementasikan method
getDefinition()untuk JSON Schema danexecute()untuk ekstraksi runtime lokal. - Jail Directory Defense: Menerapkan
basename()danrealpath()untuk mengunci pembacaan file hanya pada folder$allowedDir(Anti-Path Traversal). - Format Terdukung: Parsing native dokumen PDF (vektor layer), DOCX (Word Section), CSV, JSON terformat, dan plain TXT.
- Buffer Token Safety: Memotong konten teks pada batas
$maxChars(default: 8.000 karakter) guna mencegah token blowout di context window LLM. - Graceful Error Handling: Mengembalikan payload terstruktur
['status' => 'error', 'message' => '...']saat file korup atau tidak ditemukan.
Bedah Mekanisme Keamanan Path Traversal & Error Handling:
1. Sanitasi basename() & Jail Directory: Penggunaan basename() secara otomatis melucuti manipulasi path seperti ../../etc/passwd atau ..\..\Windows\win.ini. Selanjutnya, validasi str_starts_with(realpath($filepath), $this->allowedDir) memastikan file target benar-benar berada di dalam folder yang diizinkan tanpa celah symlink bypass.
2. Pembatasan Memori & Truncation Token: File dokumen berukuran puluhan megabyte dapat memicu kehabisan memori server (*Memory Exhaustion*). FileTool menolak file di atas 10 MB dan memotong string teks pada batas $maxChars (default: 8.000 karakter) agar tidak menghabiskan kuota context window model AI.
3. Graceful Error Serialization: Seluruh eksepsi parsing (misal: PDF terenkripsi password atau format DOCX korup) ditangkap dalam blok try-catch dan dikembalikan sebagai payload JSON terstruktur status: error, menjaga agen AI tetap berjalan tanpa fatal crash.
Integrasi FileTool ke dalam AI Agent PHP Loop
Berikut adalah contoh skrip eksekusi pengujian membaca laporan penjualan PDF:
<?php
// run-agent-file.php
require_once __DIR__ . '/vendor/autoload.php';
use App\OpenAIClient;
use App\Agent\Agent;
use App\Tools\FileTool;
$client = new OpenAIClient(getenv('OPENAI_API_KEY'));
$agent = new Agent($client, maxIterations: 5);
// Registrasikan FileTool dengan direktori uploads
$agent->registerTool(new FileTool(allowedDir: __DIR__ . '/uploads', maxFileSizeMB: 10, maxChars: 8000));
// Instruksi membaca dokumen
$prompt = 'Baca file "laporan-penjualan-q3.pdf", kemudian buatkan ringkasan 3 poin utama keuntungan perusahaan.';
$response = $agent->run($prompt);
echo "Hasil Analisis AI Agent:\n" . $response . "\n";Penanganan Dokumen Besar (>10MB): Direct FileTool vs Streaming Chunking RAG
Membaca dokumen masif berukuran puluhan megabyte (seperti laporan tahunan 200 halaman atau log server 50MB) secara utuh ke dalam memori PHP akan memicu batas memory_limit dan melampaui kapasitas context window model AI. Berikut adalah strategi perbandingan arsitektural untuk menangani file besar:
| Dimensi Penanganan | Direct FileTool (In-Memory Buffer) | Streaming & Chunking RAG (Enterprise) |
|---|---|---|
| Ukuran Dokumen Ideal | File kecil hingga menengah (<10 MB, <20 halaman) | File raksasa (>10 MB – 500 MB, ratusan halaman) |
| Metode Konsumsi Memori | Memuat teks utuh ke RAM (rentan memory_limit jika tidak dibatasi) | Membaca secara stream baris per baris via generator PHP |
| Penggunaan Token LLM | Mengirim ribuan kata sekaligus (berisiko token blowout) | Hanya mengirim 3–5 chunk paling relevan via Vector Search |
| Waktu Latensi Respons | Sangat cepat (<200ms) untuk file ringkas | Memerlukan tahap pra-indeks (Embedding Vector Database) |
| Ketepatan Konteks | Cocok untuk membaca dokumen tunggal secara menyeluruh | Sangat akurat untuk Q&A spesifik pada ribuan halaman arsip |
Pola Implementasi Generator Stream di PHP:
Untuk file CSV/TXT besar, gunakan generator yield untuk memecah teks per 1.000 karakter (*sliding window chunking*) dengan overlap 100 karakter sebelum di-generate embedding-nya ke pgvector / Qdrant.
RAG Strategy Takeaway: Gunakan Direct FileTool untuk interaksi dokumen instan, dan alihkan ke pipeline RAG Chunking jika dokumen melebihi kuota 10 MB.
FAQ: Pertanyaan Seputar Tool Membaca File AI Agent PHP
1. Bagaimana cara mencegah serangan Path Traversal pada FileTool?
Ringkasan Jawaban:Gunakan fungsibasename()untuk mengekstrak murni nama file dan verifikasi path absolut menggunakanrealpath()untuk memastikan file berada di dalam direktori$allowedDir.
Ini mencegah penyerang menyisipkan karakter dot-dot-slash (../../) untuk membaca file sensitif sistem seperti .env atau /etc/shadow.
2. Mengapa teks file perlu dipotong (truncation) sebelum dikirimkan ke AI?
Ringkasan Jawaban:Memotong teks pada batas aman (misal: 8.000 karakter) mencegah lonjakan konsumsi token (*token blowout*) dan menghindari error batas maksimal context window LLM.
Untuk dokumen sangat panjang (ratusan halaman), pertimbangkan penerapan teknik chunking dan vector embeddings (RAG) pada bab lanjutan.
3. Library apa yang direkomendasikan untuk membaca PDF dan DOCX di PHP?
Ringkasan Jawaban:Gunakansmalot/pdfparseruntuk ekstraksi teks dokumen PDF danphpoffice/phpworduntuk membaca dokumen Microsoft Word DOCX.
Kedua library ini berjalan murni di PHP tanpa memerlukan ekstensi biner tambahan atau instalasi utilitas CLI eksternal.
Rusmawan Abdullah Sani
Lead Software Engineer & System Architect
Praktisi pengembangan backend PHP modern, arsitektur AI Agent, microservices, dan otomasi server Linux. Terhubung melalui profil LinkedIn.