back to top

PHP: leggere il contenuto di file PDF, DOC e DOCX

In determinati contesti puรฒ essere utile interagire con file PDF o DOC attraverso codice PHP. Lโ€™interazione con questi file, infatti, puรฒ essere molto meno semplice di quello che si puรฒ pensare! Sia i PDF che i file DOC (il formato di Microsoft Word), infatti, sono formati piuttosto complessi che richiedono lโ€™intermediazione di un parser affinchรฉ possa esserne compreso, estrapolato e/o manipolato il contenuto.

In questo articolo vedremo alcune tecniche per estrarre il contenuto dai file PDF, DOC e DOCX mediante uno script PHP. Una simile attivitร  risulta utile, ad esempio, se si ha la necessitร  di indicizzare una serie di file di questo tipo, consentendone la ricerca attraverso un motore di ricerca interno ad un sito web.

Pubblicitร 

Si pensi, ad esempio, al sito di una scuola o ad un archivio di documenti: in ambiti come questi, riuscire ad โ€œinterpretareโ€ il contenuto dei file potrebbe rivelarsi determinante al fine di offrire agli utenti idonee funzionalitร  di ricerca.

In situazioni come questa, quindi, potrebbe essere davvero molto interessante realizzare uno spider PHP in grado di estrarre il contenuto (testuale) dai file documentali per poterli indicizzare correttamente, ad esempio archiviandone il contenuto allโ€™interno di un database.

Si noti che in questo articolo non vedremo come realizzare il motore di ricerca di cui abbiamo fatto menzione, ma ci limiteremo ad approfondire le tecniche attraverso le quali รจ possibile convertire un file PDF o Word in testo mediante PHP.

Estrarre il contenuto da un file PDF

Per poter effettuare questa operazione รจ necessario installare nel sistema unโ€™apposita libreria che funga, appunto, da parser. Nello specifico potremo far ricorso a XPDF Reader, un toolkit che include al suo interno diversi componenti tra cui pdftotext, un componente in grado di convertire un file PDF in plain text.

Una volta installato il pacchetto, potremo eseguire il seguente codice PHP:

// path del file PDF
$pdfpath = '/home/documenti/miofile.pdf';

// estraggo il contenuto
$text = shell_exec('/usr/local/bin/pdftotext ' . escapeshellarg($pdfpath) . ' -');

La nostra variabile $text conterrร  il testo estratto dal PDF elaborato.

Estrarre il contenuto da file DOC

Anche in questo caso รจ necessario scaricare un pacchetto. Si tratta di Antiword, un reader gratuito per i file generati da MS Word. Una volta installato, potremo procedere similmente a quanto visto per i file PDF:

// path del file DOC
$docpath = '/home/documenti/miofile.doc';

// estraggo il contenuto
$text = shell_exec('/usr/local/bin/antiword ' . escapeshellarg($docpath));

Si noti che la libreria in questione, essendo decisamente vecchiotta, funziona unicamente con i file โ€œ.docโ€ e non con quelli โ€œ.docxโ€ generati dalle versioni piรน recenti dellโ€™editor di testo della suite per lโ€™ufficio di casa Microsoft.

Estrarre il contenuto da file DOCX

Nel caso dei file con estensione โ€œ.docxโ€ sarร  necessario operare attraverso lโ€™ausilio di un altro tool. Nello specifico, sarร  possibile fare ricorso a docx2text, un tool da linea di comando scritto in Perl che svolge, appunto, la conversione di un file DOCX in testo semplice.

// path del file DOCX
$docxpath = '/home/documenti/miofile.docx';

// estraggo il contenuto
$text = shell_exec('/usr/local/bin/docx2txt.pl ' . escapeshellarg($docxpath));

Convertire in testo qualsiasi file Microsoft Office

Vi segnalo, infine, una interessante classe in puro PHP attraverso la quale convertire in testo il contenuto di qualsiasi file generato da MS Office: doc, docx, xlsx e pptx. La classe deve, ovviamente, essere inclusa allโ€™interno del nostro progetto.

Di seguito il contenuto della classe per la conversione di file Microsoft Office in testo:

class DocxConversion {
  private $filename;

  public function __construct($filePath) {
    $this->filename = $filePath;
  }

  private function read_doc() {
    $fileHandle = fopen($this->filename, "r");
    $line = @fread($fileHandle, filesize($this->filename));
    $lines = explode(chr(0x0D), $line);
    $outtext = "";
    foreach ($lines as $thisline) {
      $pos = strpos($thisline, chr(0x00));
      if (($pos !== FALSE) || (strlen($thisline) == 0)) {} else {
        $outtext .= $thisline . " ";
      }
    }
    $outtext = preg_replace("/[^a-zA-Z0-9\s\,\.\-\n\r\t@\/\_\(\)]/", "", $outtext);
    return $outtext;
  }

  private function read_docx() {
    $striped_content = '';
    $content = '';
    $zip = zip_open($this->filename);
    if (!$zip || is_numeric($zip)) return false;
    while ($zip_entry = zip_read($zip)) {
      if (zip_entry_open($zip, $zip_entry) == FALSE) continue;
      if (zip_entry_name($zip_entry) != "word/document.xml") continue;
      $content .= zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
      zip_entry_close($zip_entry);
    }
    zip_close($zip);
    $content = str_replace('', " ", $content);
    $content = str_replace('', "\r\n", $content);
    $striped_content = strip_tags($content);
    return $striped_content;
  }

  private function xlsx_to_text($input_file) {
    $xml_filename = "xl/sharedStrings.xml"; //content file name
    $zip_handle = new ZipArchive;
    $output_text = "";
    if (true === $zip_handle->open($input_file)) {
      if (($xml_index = $zip_handle->locateName($xml_filename)) !== false) {
        $xml_datas = $zip_handle->getFromIndex($xml_index);
        $xml_handle = DOMDocument::loadXML($xml_datas, LIBXML_NOENT | LIBXML_XINCLUDE | LIBXML_NOERROR | LIBXML_NOWARNING);
        $output_text = strip_tags($xml_handle->saveXML());
      } else {
        $output_text .= "";
      }
      $zip_handle->close();
    } else {
      $output_text .= "";
    }
    return $output_text;
  }

  private function pptx_to_text($input_file) {
    $zip_handle = new ZipArchive;
    $output_text = "";
    if (true === $zip_handle->open($input_file)) {
      $slide_number = 1; //loop through slide files
      while (($xml_index = $zip_handle->locateName("ppt/slides/slide" . $slide_number . ".xml")) !== false) {
        $xml_datas = $zip_handle->getFromIndex($xml_index);
        $xml_handle = DOMDocument::loadXML($xml_datas, LIBXML_NOENT | LIBXML_XINCLUDE | LIBXML_NOERROR | LIBXML_NOWARNING);
        $output_text .= strip_tags($xml_handle->saveXML());
        $slide_number++;
      }
      if ($slide_number == 1) {
        $output_text .= "";
      }
      $zip_handle->close();
    } else {
      $output_text .= "";
    }
    return $output_text;
  }

  public function convertToText() {
    if (isset($this->filename) && !file_exists($this->filename)) {
      return "File Not exists";
    }
    $fileArray = pathinfo($this->filename);
    $file_ext = $fileArray['extension'];
    if ($file_ext == "doc" || $file_ext == "docx" || $file_ext == "xlsx" || $file_ext == "pptx") {
      if ($file_ext == "doc") {
        return $this->read_doc();
      } elseif ($file_ext == "docx") {
        return $this->read_docx();
      } elseif ($file_ext == "xlsx") {
        return $this->xlsx_to_text();
      } elseif ($file_ext == "pptx") {
        return $this->pptx_to_text();
      }
    } else {
      return "Invalid File Type";
    }
  }
}

Una volta inclusa la classe, potrร  essere utilizzata in questo modo:

$docObj = new DocxConversion("/home/documenti/miofile.docx");
$text = $docObj->convertToText();

Nellโ€™esempio abbiamo passato in argomento un file โ€œ.docxโ€, ma nulla vieta di utilizzare la classe, come detto, con altre tipologie di file della famiglia Microsoft Office.

In conclusione, estrarre il contenuto da file PDF e DOC/DOCX mediante PHP puรฒ risultare estremamente utile in diverse situazioni, come la creazione di archivi, la digitalizzazione di documenti, e molto altro. Assicuratevi di testare a fondo i vostri script e, se necessario, consultare la documentazione delle librerie utilizzate per ulteriori funzionalitร  e opzioni.

Altri contenuti interessanti

Pubblicitร 

Potrebbero interessarti queste guide

Massimiliano Bossi
Massimiliano Bossi
Stregato dalla rete sin dai tempi delle BBS e dei modem a 2.400 baud, ho avuto la fortuna di poter trasformare la mia passione in un lavoro (nonostante una Laurea in Giurisprudenza). Adoro scrivere codice e mi occupo quotidianamente di comunicazione, design e nuovi media digitali. Orgogliosamente "nerd" sono il fondatore di MRW.it (per il quale ho scritto centinaia di articoli) e di una nota Web-Agency (dove seguo in prima persona progetti digitali per numerosi clienti sia in Italia che all'estero).

Leggi anche...

Cannot modify header information โ€“ headers already sent: come risolvere lโ€™errore PHP

L'errore di PHP cannot modify header information - headers...

Ricavare lโ€™estensione di un file con PHP

Quando si lavora con i file in un'applicazione web,...

GD Library: creazione, manipolazione e ridimensionamento immagini con PHP

Le librerie GD (o GD Library), sono componenti fondamentali...

PHP: impostare il fuso orario italiano

Le tue pagine PHP non mostrano lโ€™orario corretto? Probabilmente...

PHP BBCode: script pronti allโ€™uso

A volte puรฒ aversi l'esigenza di dover offrire agli...
Pubblicitร