SDK PHP per la Conversione dei File#
enconvert/enconvert-php è il client PHP ufficiale per l'API EnConvert. Installalo con Composer, dagli una chiave API e ottieni due cose: nove metodi di conversione che trasformano URL, immagini e documenti in PDF, PNG, Markdown e formati di dati, e un namespace $client->v2 che legge il web live in Markdown pronto per gli agenti, screenshot e JSON strutturato. Richiede PHP 8.1+, è costruito su Guzzle 7, usa array di opzioni in camelCase ovunque e restituisce oggetti risultato tipizzati readonly invece di array generici. Le conversioni lunghe che superano un timeout HTTP vengono recuperate automaticamente con il polling del job.
enconvert/enconvert-php · Sorgente: conversionapi/php-sdk · PHP: 8.1+ · Richiede: guzzlehttp/guzzle ^7.8
Installazione#
composer require enconvert/enconvert-php
Il pacchetto viene caricato in autoload sotto il namespace PSR-4 Enconvert\ e non include né CLI, né file di configurazione, né service provider. Funziona senza modifiche in PHP puro, Laravel, Symfony, WordPress e in qualsiasi progetto PSR-4.
Avvio rapido#
<?php
require __DIR__ . '/vendor/autoload.php';
use Enconvert\Client;
$client = new Client(getenv('ENCONVERT_API_KEY'));
// Converte una pagina live in PDF e la trasmette in streaming direttamente su disco.
$result = $client->convertUrlToPdf('https://example.com', [
'saveTo' => 'page.pdf',
]);
echo $result->presignedUrl, ' ', $result->fileSize, ' bytes', PHP_EOL;
// Leggere una pagina per un agente usa lo stesso client e la stessa chiave.
$op = $client->v2->perceive('https://example.com', ['outputs' => ['markdown', 'structured']]);
echo $op->renderQuality, PHP_EOL; // da 0.0 a 1.0, ad es. 0.93
echo $op->outputs['markdown']->url, PHP_EOL; // URL di download firmato
L'SDK è solo lato server. Una chiave privata (sk_live_...) non deve mai arrivare a un browser o a un'app mobile.
Cosa espone il client#
| Superficie | Come ci arrivi | Che cosa fa |
|---|---|---|
| Conversione di file e URL | $client->convert*() |
Nove metodi su POST /v1/convert/*, più tre helper per il polling di job e batch. |
| Web intelligence (V2) | $client->v2 (oppure $client->v2()) |
Ventitré metodi su /v2/*: perceive, discover, lookup, distill, ingest, watch. |
| Introspezione dei formati | Enconvert\Formats |
Le 43 coppie {input}-to-{output} implementate, la ricerca del MIME e gli elenchi di output per ciascun input. |
| Errori | Enconvert\Exception\* |
La base EnconvertException più ApiException, AuthenticationException, QuotaException, RateLimitException. |
| Risultati | Enconvert\Model\* |
Value object readonly con proprietà in camelCase. |
$client->v2 è una proprietà pubblica readonly. $client->v2() è un accessore identico per chi preferisce la sintassi a metodo. Ogni endpoint V2 richiede una chiave API privata; le chiavi pubbliche vengono rifiutate.
Conversione dei file#
Ogni metodo su singolo file restituisce un ConversionResult che porta un URL di download presigned. Passa saveTo e l'SDK trasmette anche i byte in streaming su quel percorso locale, creando le directory padre se servono.
convertUrlToPdf#
Esegue il rendering in PDF di qualsiasi URL raggiungibile.
$result = $client->convertUrlToPdf('https://example.com', [
'singlePage' => false,
'pdfOptions' => ['pageSize' => 'A4', 'orientation' => 'landscape'],
'viewportWidth' => 1440,
'saveTo' => 'report.pdf',
]);
| Opzione | Tipo | Predefinito | Descrizione |
|---|---|---|---|
saveTo |
string |
nessuno | Percorso locale su cui trasmettere il PDF in streaming. Le directory padre vengono create. |
singlePage |
bool |
true |
true produce una singola pagina continua. false pagina utilizzando pdfOptions.pageSize. |
pdfOptions |
array |
nessuno | Dimensione pagina, orientamento, margini, scala, scala di grigi, intestazione, piè di pagina. Vedi Opzioni PDF. |
viewportWidth, viewportHeight |
int |
1920, 1080 |
Dimensione del viewport del browser in pixel. |
loadMedia |
bool |
true |
Attende immagini e video prima della cattura. |
enableScroll |
bool |
true |
Scorre dall'alto verso il basso perché scattino i caricamenti lazy. |
outputFilename |
string |
auto | Sovrascrive il nome file generato. |
auth, cookies, headers |
array |
nessuno | Accesso alla pagina: Basic Auth ['username' => ..., 'password' => ...], cookie iniettati, header di richiesta personalizzati. |
auth con un header Authorization. L'API rifiuta il conflitto invece di indovinare quale credenziale intendevi.
convertUrlToScreenshot#
Cattura un PNG di qualsiasi URL.
$shot = $client->convertUrlToScreenshot('https://example.com', [
'viewportWidth' => 1440,
'saveTo' => 'shot.png',
]);
Accetta le stesse opzioni di viewport, media, scroll, nome file e accesso alla pagina di convertUrlToPdf, meno singlePage e pdfOptions.
convertUrlToMarkdown#
Estrae Markdown pulito in stile GitHub-Flavored da un URL. Navigazione, footer, pubblicità e script vengono rimossi, il corpo principale dell'articolo viene mantenuto e viene anteposto un frontmatter YAML (titolo, descrizione, url, link, immagini).
$md = $client->convertUrlToMarkdown('https://example.com/article', [
'saveTo' => 'article.md',
]);
Stesso insieme di opzioni di convertUrlToScreenshot.
convertImage#
Converte tra jpeg, png, svg, heic e webp, oppure rasterizza un PDF in JPEG.
// Da un percorso.
$client->convertImage('photo.heic', ['outputFormat' => 'webp', 'saveTo' => 'photo.webp']);
// Da byte grezzi. Il nome file determina il formato di input e il tipo MIME.
$client->convertImage(
['data' => file_get_contents('photo.heic'), 'filename' => 'photo.heic'],
['outputFormat' => 'webp', 'saveTo' => 'photo.webp']
);
$client->convertImage('scan.pdf', ['outputFormat' => 'jpeg', 'saveTo' => 'scan.jpeg']); // rasterizza
Il formato di input viene ricavato dall'estensione del file: .jpg, .jpeg, .png, .svg, .heic, .webp e .pdf. Il formato di output è obbligatorio e viene normalizzato automaticamente, quindi jpg diventa jpeg.
| Opzione | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
outputFormat |
string |
Sì | Uno tra jpeg, png, svg, heic, webp. |
saveTo |
string |
No | Percorso locale su cui trasmettere il risultato in streaming. |
outputFilename |
string |
No | Sovrascrive il nome file generato. |
convertDocument#
Converte documenti e formati di dati. outputFormat vale pdf per impostazione predefinita.
// da docx a pdf, poi da json a yaml
$client->convertDocument('report.docx', ['saveTo' => 'report.pdf']);
$client->convertDocument('data.json', ['outputFormat' => 'yaml', 'saveTo' => 'data.yaml']);
// da markdown a pdf con impostazioni di pagina
$client->convertDocument('README.md', [
'outputFormat' => 'pdf',
'pdfOptions' => ['pageSize' => 'A4', 'margins' => ['top' => 20, 'bottom' => 20]],
'saveTo' => 'readme.pdf',
]);
Estensioni di input riconosciute: .doc, .docx, .xls, .xlsx, .ppt, .pptx, .html, .htm, .odt, .ods, .odp, .ots, .pages, .numbers, .md, .markdown, .csv, .json, .xml, .yaml, .yml, .toml.
| Opzione | Tipo | Predefinito | Descrizione |
|---|---|---|---|
outputFormat |
string |
"pdf" |
Formato di destinazione. Gli alias jpg, yml, htm e md vengono risolti. |
saveTo |
string |
nessuno | Percorso locale su cui trasmettere il risultato in streaming. |
outputFilename |
string |
nessuno | Sovrascrive il nome file generato. |
pdfOptions |
array |
nessuno | Impostazioni di pagina. Rispettate quando l'output è PDF. |
EPUB non ha una coppia documentale dedicata. Invia i file .epub a convertToPdf oppure a convertToMarkdown.
Coppie di conversione supportate#
| Input | Output |
|---|---|
json |
csv, toml, xml, yaml |
xml |
csv, json |
yaml, toml |
json |
csv |
json, xml |
markdown |
html, pdf |
html |
pdf |
doc, excel, ppt, odt, ods, odp, ots, pages, numbers |
pdf |
jpeg, png, svg, heic, webp |
tra loro (tutte le 20 coppie) |
pdf |
jpeg |
L'SDK valida la coppia {input}-to-{output} rispetto a quella tabella e genera EnconvertException prima che qualsiasi richiesta lasci il tuo processo, con nel messaggio l'elenco degli output validi per quell'input. Puoi interrogare direttamente la stessa tabella:
use Enconvert\Formats;
Formats::validOutputsFor('json'); // ["csv", "toml", "xml", "yaml"]
Formats::validOutputsFor('pdf'); // ["jpeg"]
Formats::normalizeOutputFormat('JPG'); // "jpeg"
Formats::mimeFor('deck.pptx'); // il tipo MIME del PPTX
count(Formats::IMPLEMENTED_CONVERSIONS); // 43
convertToMarkdown#
Rileva automaticamente lato server il formato di un documento e restituisce Markdown. È il mattone per l'ingestion RAG dei file che hai già su disco.
$client->convertToMarkdown('handbook.docx', ['saveTo' => 'handbook.md']);
Accetta PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT/MD e file office legacy oppure ODF. Le immagini non sono supportate. Le opzioni sono saveTo e outputFilename; su questo endpoint non ci sono opzioni PDF.
convertToPdf#
Rileva automaticamente quasi qualsiasi input e restituisce un PDF.
$client->convertToPdf('slides.pptx', ['saveTo' => 'slides.pdf']);
// Un input PDF viene passato in passthrough, quindi questo funziona anche come percorso di normalizzazione in scala di grigi.
$client->convertToPdf('scan.pdf', ['pdfOptions' => ['grayscale' => true], 'saveTo' => 'gray.pdf']);
Accetta office, ODF, Pages, Numbers, RTF, CSV, HTML, Markdown, testo semplice, immagini raster, SVG, EPUB e un PDF esistente in passthrough.
pdfOptions.grayscale. Il formato viene rilevato lato server, quindi la geometria di pagina proviene dal documento di origine. Usa convertDocument oppure convertUrlToPdf quando ti servono dimensione pagina, margini, orientamento, intestazioni o piè di pagina.
convertWebsiteToPdf e convertWebsiteToScreenshot#
Individua ogni pagina di un sito, converte ciascuna in background e raccoglie un unico ZIP. Entrambi sono asincroni e restituiscono un BatchSubmission invece di un ConversionResult. Richiedono una chiave API privata con accesso al crawl.
$batch = $client->convertWebsiteToPdf('https://example.com', [
'crawlMode' => 'sitemap', // "auto" (predefinito) | "sitemap" | "full"
'excludePatterns' => ['/blog/tag/'], // solo in modalità full crawl
'notificationEmail' => '[email protected]',
]);
echo $batch->batchId, ' ', $batch->urlCount, ' ', $batch->discoveryMethod, PHP_EOL;
// Blocca finché il batch non esce da "processing", poi salva lo ZIP.
$status = $client->waitForBatch($batch->batchId, ['saveTo' => 'site.zip']);
echo $status->completed, ' of ', $status->total, ' pages converted', PHP_EOL;
// Oppure esegui tu stesso il polling con getBatchStatus().
$s = $client->getBatchStatus($batch->batchId);
echo $s->status === 'processing' ? 'still working' : $s->zipDownloadUrl, PHP_EOL;
convertWebsiteToScreenshot accetta le stesse opzioni meno singlePage e pdfOptions, e produce uno ZIP di PNG.
| Opzione | Tipo | Predefinito | Descrizione |
|---|---|---|---|
crawlMode |
string |
"auto" |
auto, sitemap oppure full. |
includePatterns, excludePatterns |
string[] |
nessuno | Mantiene o scarta gli URL in base al pattern. Le esclusioni si applicano in modalità full crawl. |
notificationEmail, callbackUrl |
string |
nessuno | Indirizzo email e webhook da avvisare al completamento. |
viewportWidth, viewportHeight, loadMedia, enableScroll |
misto | predefinito del server | Opzioni di rendering per pagina. Inviate solo quando le imposti. |
auth, cookies, headers |
array |
nessuno | Accesso alle pagine per siti protetti da login. |
outputFilename |
string |
nessuno | Sovrascrive il nome file dello ZIP. |
waitForBatch accetta intervalMs (predefinito 5000), timeoutMs (predefinito 1800000, cioè 30 minuti) e saveTo. Genera ApiException con stato 504 se il limite scade mentre il batch è ancora in elaborazione.
getJobStatus#
Interroga un singolo job di conversione asincrono o recuperato.
$status = $client->getJobStatus('job_abc123');
if ($status->status === 'success') {
echo $status->presignedUrl, PHP_EOL;
} elseif ($status->status === 'failed') {
echo $status->error, PHP_EOL;
}
Restituisce un JobStatus con status (processing, success oppure failed), presignedUrl, objectKey ed error. Raramente ti serve direttamente, perché l'SDK esegue il polling per tuo conto. Vedi Recupero dei timeout.
Web intelligence (V2)#
Il namespace $client->v2 trasforma le pagine web live in dati pronti per gli agenti: rendering, ricerca, estrazione, ingestion e monitoraggio. Ogni lettura porta con sé renderQuality, un punteggio da 0.0 a 1.0 che distingue un rendering reale da uno fallito. Una pagina di challenge, un cookie wall, una schermata di login o uno shell SPA vuoto tornano con un punteggio basso e con warnings popolati, così una lettura difettosa non entra mai silenziosamente nel contesto di un agente. Il contenuto viene comunque restituito: è segnalato, non nascosto. I concetti sono spiegati nella panoramica V2.
Perceive#
Esegue il rendering di un URL e materializza tutti gli output che hai richiesto da quel singolo rendering. Vedi il riferimento di perceive.
$op = $client->v2->perceive('https://example.com/pricing', [
'outputs' => ['markdown', 'screenshot', 'structured'],
'extract' => ['tables', 'metadata'],
'onlyMainContent' => true,
'waitFor' => '.price',
]);
echo $op->renderQuality, ' ', $op->statusCode, PHP_EOL; // punteggio, stato HTTP a monte
print_r($op->deductions); // ad es. ["login_wall" => 0.65]
echo $op->outputs['markdown']->url, PHP_EOL; // URL firmato, 15 minuti
print_r($op->structured);
// Gli URL firmati scadono. Rifirmali in seguito senza rifare il rendering.
$again = $client->v2->getPerceiveOperation($op->operationId);
| Opzione | Tipo | Descrizione |
|---|---|---|
outputs |
string[] |
Uno o più tra markdown, html_cleaned, html_raw, screenshot, screenshot_full_page, pdf, links, images, structured. |
extract |
string[] |
Campi strutturati da estrarre, per esempio metadata, structured_data, headings, tables, main_content, all. |
schema |
array |
Schema per l'estrazione strutturata basata su LLM. |
onlyMainContent |
bool |
Rimuove gli elementi di contorno del sito dall'output Markdown. |
waitFor, waitTimeoutMs |
string, int |
Attende un selettore CSS o un'espressione JS dopo la navigazione. |
jsCode |
string |
JavaScript da eseguire sulla pagina dopo la navigazione. |
viewport, mobile, blockResources |
array, bool, string[] |
Geometria di rendering e tipi di risorsa da interrompere prima che vengano caricati. |
cacheMode |
string |
enabled, bypass oppure refresh. |
headers, cookies, auth |
array |
Accesso alle pagine autenticate. |
respectRobots |
bool |
Rifiuta gli URL vietati da robots.txt. |
pdfOptions |
array |
Impostazioni di pagina per l'output pdf. |
directDownload |
bool |
Restituisce i byte grezzi dell'artefatto. Accettato solo da perceive(). |
proxyUrl, geolocation, actionChain |
misto | Serializzati dall'SDK, riservati dall'API. |
Percezione in batch#
$batch = $client->v2->perceiveBatch(['https://a.com', 'https://b.com'], [
'outputs' => ['markdown'],
'outputMode' => 'zip',
]);
// I batch piccoli si completano inline. Quelli più grandi tornano in coda, quindi vanno interrogati.
if ($batch->status !== 'completed') {
$batch = $client->v2->getPerceiveBatch($batch->jobId);
}
foreach ($batch->items as $item) {
echo $item->url, ' ', $item->renderQuality, PHP_EOL;
}
echo $batch->zip?->url, PHP_EOL;
Fino a 1000 URL condividono un unico blocco di opzioni. outputMode è manifest (predefinito) oppure zip. Qui directDownload non è accettato.
Streaming di un singolo artefatto#
perceiveDirect() salta l'envelope JSON e ti consegna i byte. Deve essere richiesto esattamente un output che produca artefatti, e l'SDK lo verifica prima dell'invio, quindi structured da solo genera un'eccezione.
$direct = $client->v2->perceiveDirect('https://example.com', [
'outputs' => ['pdf'],
]);
file_put_contents($direct->filename ?? 'page.pdf', $direct->content);
echo $direct->renderQuality, ' ', $direct->contentType, PHP_EOL;
echo $direct->operationId, ' cache hit: ', var_export($direct->cacheHit, true), PHP_EOL;
// Riscarica in seguito un artefatto archiviato. Ometti il nome dell'output quando
// l'operazione ha prodotto esattamente un artefatto.
$saved = $client->v2->downloadPerceiveArtifact($direct->operationId, 'pdf');
PerceiveDirectResult porta content, contentType, filename, operationId, objectKey, cacheHit, renderQuality, sourceStatusCode, contentHash e warningsCount. Un ApiException con stato 410 significa che l'artefatto archiviato non è più disponibile.
Discover#
Enumera gli URL di un sito solo via HTTP. Nessun rendering nel browser, quindi è veloce. Vedi il riferimento di discover.
$found = $client->v2->discover('https://example.com', [
'mode' => 'hybrid', // "sitemap" | "crawl" | "hybrid"
'maxUrls' => 200,
'maxDepth' => 3,
'excludePatterns' => ['/tag/'],
'sameDomainOnly' => true,
]);
echo $found->total, ' urls, truncated: ', var_export($found->truncated, true), PHP_EOL;
print_r($found->sources); // ad es. ["sitemap" => 42, "crawl" => 30]
Le opzioni sono mode, maxUrls, maxDepth, includePatterns, excludePatterns, sameDomainOnly e respectRobots.
Lookup#
Esegue una ricerca web categorizzata e, facoltativamente, renderizza automaticamente i risultati migliori. Vedi il riferimento di lookup.
$search = $client->v2->lookup('best static site generators', [
'category' => 'web', // web | news | images | scholar | patents | maps
'numResults' => 10,
'country' => 'us',
'timeFilter' => 'month',
'perceiveTop' => 3, // renderizza automaticamente i 3 risultati migliori
]);
foreach ($search->results as $hit) {
echo $hit->position, '. ', $hit->title, ' ', $hit->url, PHP_EOL;
echo ' quality ', $hit->perceive?->renderQuality ?? 'not perceived', PHP_EOL;
}
Le opzioni sono category, country, locale, timeFilter, numResults, page, location, autocorrect e perceiveTop.
Distill#
Estrazione strutturata guidata da schema su un elenco di URL o su un sito individuato automaticamente. Vedi il riferimento di distill.
$extraction = $client->v2->distill([
'urls' => ['https://example.com/pricing'],
'schema' => ['plans' => 'list of plan names with monthly prices'],
'cssSchema' => [ // passaggio CSS gratuito opzionale prima del livello LLM
'baseSelector' => '.plan-card',
'fields' => [
['name' => 'name', 'type' => 'text', 'selector' => 'h3'],
['name' => 'price', 'type' => 'text', 'selector' => '.price'],
],
],
]);
print_r($extraction->results[0]->data);
echo $extraction->results[0]->extractionTier, PHP_EOL; // css | llm | mixed | none
echo $extraction->results[0]->fieldsFromCss, '/', $extraction->results[0]->fieldsFromLlm, PHP_EOL;
// Oppure individua prima l'insieme di URL.
$client->v2->distill([
'discoverFrom' => ['url' => 'https://example.com', 'mode' => 'sitemap', 'maxPages' => 10],
'schema' => ['title' => 'page title', 'summary' => 'one-line summary'],
]);
schema è obbligatorio, ed esattamente uno tra urls e discoverFrom deve essere presente. Se violi una delle due regole, l'SDK genera EnconvertException prima dell'invio. Le altre opzioni sono waitFor, waitTimeoutMs, headers, cookies e respectRobots.
Ingest#
Trasforma un intero sito, o una pila di documenti caricati, in JSONL suddiviso in chunk e pronto per il RAG attraverso un'unica pipeline. Ingest è sempre asincrono. Vedi il riferimento di ingest.
// Da un sito.
$job = $client->v2->ingest([
'mode' => 'sitemap', // "urls" (predefinito) | "sitemap" | "crawl"
'url' => 'https://docs.example.com',
'maxPages' => 100,
'chunk' => ['maxWords' => 512, 'sentenceOverlap' => 1],
'webhookUrl' => 'https://my.app/hooks/enconvert',
]);
// Oppure da file caricati: PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT/MD, office legacy e ODF.
$fileJob = $client->v2->ingestFiles(['handbook.pdf', 'notes.docx'], [
'chunk' => ['maxWords' => 512, 'sentenceOverlap' => 1],
]);
// Esegui il polling finché non arriva.
do {
sleep(5);
$status = $client->v2->getIngestJob($job->jobId);
} while (in_array($status->status, ['queued', 'discovering', 'processing'], true));
if ($status->status === 'completed') {
echo $status->totalChunks, ' chunks: ', $status->outputUrl, PHP_EOL; // JSONL firmato
}
mode vale urls per impostazione predefinita, il che richiede un array urls non vuoto e rifiuta url. Le modalità sitemap e crawl richiedono un url seed e rifiutano urls. L'SDK applica entrambe le regole localmente. Le altre opzioni sono maxPages, maxDepth, sameDomainOnly, includePatterns, excludePatterns, respectRobots, waitFor, waitTimeoutMs, chunk e webhookUrl.
// Gestione dei job.
$list = $client->v2->listIngestJobs(['limit' => 20, 'skip' => 0]);
foreach ($list->jobs as $summary) {
echo $summary->jobId, ' ', $summary->status, ' ', $summary->totalChunks, PHP_EOL;
}
$client->v2->cancelIngestJob($job->jobId); // idempotente
// Firma dei webhook.
$secret = $client->v2->getWebhookSecret();
echo $secret->signatureHeader, ' ', $secret->signatureScheme, PHP_EOL;
$client->v2->rotateWebhookSecret(); // le vecchie firme smettono di essere valide
$client->v2->retryIngestWebhook($job->jobId); // rispedisce una callback di completamento
Watch#
Rifà il rendering di un URL a cadenza fissa e ti avvisa quando cambia. Vedi il riferimento di watch.
$watcher = $client->v2->createWatcher('https://example.com/pricing', [
'frequencyMinutes' => 60, // minimo orario
'diffMode' => 'auto', // auto | text | structured | tables | metadata
'webhookUrl' => 'https://my.app/hooks/changes',
'notifyEmail' => true,
]);
echo $watcher->watcherId, ' next check ', $watcher->nextCheckAt, PHP_EOL;
$snapshots = $client->v2->getWatcherSnapshots($watcher->watcherId, ['limit' => 10]);
foreach ($snapshots->snapshots as $snap) {
if ($snap->hasChanges) {
echo $snap->checkedAt, ' similarity ', $snap->similarity,
' changes ', $snap->changeCount, PHP_EOL;
}
}
$client->v2->updateWatcher($watcher->watcherId, ['status' => 'paused']);
$client->v2->updateWatcher($watcher->watcherId, ['webhookUrl' => '']); // cancella il webhook
$client->v2->deleteWatcher($watcher->watcherId); // soft delete, idempotente
createWatcher accetta frequencyMinutes, diffMode, trackFields, webhookUrl e notifyEmail. updateWatcher accetta quei cinque più status, e richiede almeno un campo altrimenti genera EnconvertException. listWatchers accetta skip e limit.
Opzioni PDF#
Passate come array pdfOptions su convertUrlToPdf, convertDocument, convertToPdf (solo grayscale), convertWebsiteToPdf e sul perceive V2 con un output pdf. L'SDK serializza le chiavi camelCase nel formato di trasporto dell'API e invia solo le chiavi che hai impostato.
$client->convertUrlToPdf('https://example.com', [
'pdfOptions' => [
'pageSize' => 'A4',
'orientation' => 'landscape',
'margins' => ['top' => 10, 'bottom' => 10, 'left' => 15, 'right' => 15],
'scale' => 0.9,
'header' => ['content' => 'Quarterly Report', 'height' => 15],
'footer' => ['content' => 'Page {{page}} of {{total_pages}}', 'height' => 12],
],
'singlePage' => false,
'saveTo' => 'report.pdf',
]);
| Campo | Tipo | Descrizione |
|---|---|---|
pageSize |
string |
Da A0 ad A6, da B0 a B5, Letter, Legal, Tabloid, Ledger. Ignorato quando sono impostati sia pageWidth sia pageHeight. |
pageWidth, pageHeight |
float |
Dimensione pagina personalizzata in millimetri. Vanno impostati insieme. |
orientation |
string |
portrait oppure landscape. |
margins |
array |
['top' => ..., 'bottom' => ..., 'left' => ..., 'right' => ...] in millimetri. |
scale |
float |
Scala di rendering, da 0.1 a 2.0. Solo per output paginato. |
grayscale |
bool |
Post-elabora il PDF in scala di grigi. |
header |
array |
['content' => '<html>', 'height' => 15]. Altezza in millimetri. |
footer |
array |
Stessa forma di header. |
Il contenuto di intestazione e piè di pagina supporta le variabili di template {{page}}, {{total_pages}}, {{date}}, {{title}} e {{url}}. Il riferimento completo dei parametri si trova in parametri e opzioni.
Gestione degli errori#
Tutto ciò che l'SDK genera discende da Enconvert\Exception\EnconvertException, quindi un solo blocco catch può delimitare l'intera superficie.
use Enconvert\Exception\{
ApiException, AuthenticationException, EnconvertException, QuotaException, RateLimitException
};
try {
$client->convertUrlToPdf('https://example.com', ['saveTo' => 'page.pdf']);
} catch (AuthenticationException $e) {
error_log('Check ENCONVERT_API_KEY: ' . $e->getMessage());
} catch (RateLimitException $e) {
error_log('Too many requests, back off and retry.');
} catch (QuotaException $e) {
error_log($e->getMessage());
} catch (ApiException $e) {
error_log(sprintf('API error [%d]: %s', $e->getStatusCode(), $e->getMessage()));
} catch (EnconvertException $e) {
error_log('Client-side or transport failure: ' . $e->getMessage());
}
| Classe | Generata per | Codice di stato |
|---|---|---|
AuthenticationException |
Chiave API non valida, mancante o revocata | risposte 401 e 403 |
QuotaException |
HTTP 402 | 402 |
RateLimitException |
Troppe richieste | 429 |
ApiException |
Qualsiasi altra risposta 4xx o 5xx | il codice effettivo |
EnconvertException |
Classe base, e ogni errore lato client | nessuno |
ApiException::getStatusCode() restituisce lo stato numerico; il messaggio ha come prefisso [code]. Una risposta 403 viene mappata su AuthenticationException, il cui getStatusCode() riporta 401, quindi quando devi distinguere i due casi ragiona sulla classe invece che sul numero.
EnconvertException viene generata anche senza alcun round trip di rete, quando l'SDK capisce che la richiesta è destinata a fallire: chiave API vuota, percorso file mancante, estensione file non riconosciuta, coppia di conversione non implementata, chiamata distill senza schema oppure con entrambi urls e discoverFrom, incoerenza tra la modalità di ingest e il payload, elenco ingestFiles vuoto, chiamata perceiveDirect che non indica esattamente un output di artefatto, chiamata updateWatcher senza campi, e qualsiasi errore di trasporto di Guzzle (riportato come HTTP request failed: ...).
La mappa completa dei messaggi si trova nel riferimento dei codici di errore.
Recupero dei timeout#
Le conversioni di documenti di grandi dimensioni e le pagine lente possono superare il timeout di un reverse proxy anche quando la conversione alla fine riesce sul server. L'SDK recupera da solo la situazione:
- Prima di ogni richiesta di conversione genera un job id esadecimale di 32 caratteri e lo invia come
job_idnel corpo o nel form multipart. - Se quella richiesta torna con 5xx, l'SDK smette di sollevare eccezioni e inizia a interrogare
GET /v1/convert/status/{job_id}ogni 3 secondi. - Nel momento in cui il job risulta
success, l'SDK restituisce il risultato. Se risultafailed, generaApiExceptioncon il messaggio di errore del server. - Un
404durante il polling significa che il job non è ancora stato registrato e il polling continua. Il limite è di 5 minuti, superato il quale generaApiException(504, 'Conversion timed out').
Non c'è codice da scrivere per questo. Due eccezioni volute: gli invii batch dei siti web (convertWebsiteToPdf, convertWebsiteToScreenshot) non hanno una riga per singolo job, quindi lì un 5xx emerge subito, e i metodi V2 non usano affatto il polling dei job.
Le risposte riuscite che omettono job_id vengono completate con l'id generato dal client, così $result->jobId è sempre utilizzabile con getJobStatus().
Configurazione#
use Enconvert\Client;
$client = new Client(getenv('ENCONVERT_API_KEY'), [
'timeout' => 300, // secondi
'base_url' => 'https://api.enconvert.com', // sovrascrivi per un gateway self-hosted
]);
| Opzione | Tipo | Predefinito | Descrizione |
|---|---|---|---|
$apiKey (primo argomento) |
string |
obbligatorio | Chiave API privata (sk_live_...). Una stringa vuota genera EnconvertException. |
timeout |
int\|float |
300 |
Timeout della richiesta in secondi, l'unità idiomatica di Guzzle. Si applica a ogni richiesta HTTP effettuata dal client. Il limite per il polling dei job è separato e fissato a 300 secondi. |
base_url |
string |
https://api.enconvert.com |
Host dell'API. Gli slash finali vengono rimossi. |
Nota che la chiave dell'opzione è in snake_case base_url, mentre ogni altra opzione di richiesta nell'SDK è in camelCase. Le richieste sono autenticate con un header X-API-Key; i download saveTo vanno direttamente allo storage e deliberatamente non inviano alcuna chiave, perché l'URL è già firmato.
Struttura del risultato#
Ogni conversione di un singolo file restituisce un Enconvert\Model\ConversionResult con proprietà pubbliche readonly:
final class ConversionResult
{
public readonly string $presignedUrl; // URL di download firmato
public readonly string $objectKey; // chiave dell'oggetto nello storage
public readonly string $filename; // nome file lato server
public readonly int|float|null $fileSize; // byte
public readonly int|float|null $conversionTimeSeconds;
public readonly ?string $jobId; // l'id usato per il recupero dei timeout
}
Gli URL presigned scadono dopo 15 minuti e possono essere recuperati più di una volta prima della scadenza. Per un accesso permanente, scarica i byte (passa saveTo, oppure recupera l'URL tu stesso) e archiviali nel tuo bucket.
Gli altri tipi di risultato seguono lo stesso schema: JobStatus, BatchSubmission, BatchStatus con i suoi BatchItem[] e, sotto Enconvert\Model\V2, PerceiveResult, PerceiveDirectResult, PerceiveBatchResult, OutputArtifact, DiscoverResult, LookupResult, LookupItem, DistillResult, DistillItem, IngestJob, IngestJobList, IngestJobSummary, Watcher, WatcherList, WatcherSummary, WatcherSnapshot, WatcherSnapshotList, WebhookSecret, WebhookRetryResult e Tokens. I campi sul filo arrivano in snake_case e vengono mappati su proprietà camelCase; i payload forniti dall'utente, come schemi, dati estratti, campi monitorati e voci di diff, passano intatti.
Sorgente e problemi#
- Packagist: enconvert/enconvert-php
- GitHub: conversionapi/php-sdk · apri una issue
- Licenza: MIT
- Altri client: tutti gli SDK · endpoint REST
Domande frequenti#
Come converto i file in PHP con Composer?#
Esegui composer require enconvert/enconvert-php, costruisci new Enconvert\Client($apiKey) e chiama un metodo come convertUrlToPdf, convertImage, convertDocument, convertToPdf oppure convertToMarkdown. Aggiungi saveTo a uno qualsiasi di essi e l'SDK trasmette per te i byte convertiti su quel percorso locale, creando le directory padre lungo il percorso.
Come converto DOCX in PDF in PHP?#
Chiama $client->convertDocument('report.docx', ['saveTo' => 'report.pdf']). Il formato di output predefinito è pdf, quindi non serve alcun outputFormat. Il formato di input viene letto dall'estensione del file, e l'SDK verifica la coppia doc-to-pdf rispetto alla sua tabella di 43 conversioni implementate prima di inviare qualsiasi cosa, così una coppia non supportata fallisce all'istante con un messaggio che elenca ciò che è valido per quell'input.
Come converto un URL in PDF in PHP?#
Chiama $client->convertUrlToPdf('https://example.com', ['saveTo' => 'page.pdf']). Per impostazione predefinita la pagina viene renderizzata come una singola pagina continua con un viewport 1920x1080, con il caricamento dei media e lo scroll attivi. Imposta singlePage a false e passa pdfOptions quando vuoi una vera paginazione con dimensione pagina, margini, intestazioni e piè di pagina.
Come estraggo una pagina web in PHP ottenendo Markdown pulito?#
Usa il namespace V2: $client->v2->perceive($url, ['outputs' => ['markdown', 'structured']]). Renderizza la pagina in un browser reale, quindi i siti pieni di JavaScript funzionano, e restituisce un URL Markdown firmato più dati strutturati inline. Controlla renderQuality sul risultato prima di fidarti del contenuto: un punteggio basso con deductions popolate significa che il rendering ha incontrato una pagina anti-bot, un login wall o uno shell vuoto. Per un percorso più leggero e immediato, senza funzionalità V2, funziona anche convertUrlToMarkdown.
Come converto HEIC in WebP in PHP?#
Chiama $client->convertImage('photo.heic', ['outputFormat' => 'webp', 'saveTo' => 'photo.webp']). È supportata qualsiasi coppia tra jpeg, png, svg, heic e webp, più la rasterizzazione da pdf a jpeg. Puoi anche passare byte grezzi come ['data' => $bytes, 'filename' => 'photo.heic'], dove è il nome file a determinare il formato di input e il tipo MIME.
L'SDK PHP di EnConvert funziona con Laravel o Symfony?#
Sì. Il pacchetto è una semplice libreria PSR-4 con Guzzle 7 come unica dipendenza e nessun accoppiamento a framework, quindi si inserisce senza modifiche in Laravel, Symfony, WordPress o in uno script nudo e crudo. Registra Enconvert\Client nel tuo container con la chiave presa dalla configurazione d'ambiente e iniettalo dove ti serve.
Che cosa succede quando una conversione dura più del timeout HTTP?#
L'SDK recupera da solo. Invia un job_id generato dal client con ogni richiesta di conversione e, se la richiesta restituisce 5xx, interroga silenziosamente GET /v1/convert/status/{job_id} ogni 3 secondi per un massimo di 5 minuti, restituendo il risultato non appena il job registra success. Superato il limite genera ApiException(504, 'Conversion timed out'). Gli invii batch dei siti web sono esclusi da questo meccanismo, dato che non hanno una riga per singolo job.
Per quanto tempo è valido l'URL di download presigned?#
Gli URL di download presigned scadono dopo 15 minuti e possono essere usati più di una volta prima della scadenza. Gli URL degli artefatti V2 hanno un expiresIn di 900 secondi per lo stesso motivo, e getPerceiveOperation($operationId) li rifirma a partire dalle chiavi degli oggetti archiviati senza rifare il rendering della pagina. Per qualsiasi cosa permanente, scarica i byte e tienili nel tuo storage.
Quale versione di PHP richiede l'SDK?#
PHP 8.1 o versioni successive. L'SDK usa ovunque proprietà readonly, union type in stile enum, argomenti nominati ed espressioni match, quindi la 8.0 e le precedenti non sono supportate. La sua unica dipendenza a runtime è guzzlehttp/guzzle ^7.8.