Läsa dokument (.doc, .docx, .odt, .pdf & .rtf) med php
Jag hamnade nyss i en situation där jag behövde extrahera text från dokument. Syftet var att senare kunna låta Sphinx indexera datat. Målbilden var att klara av .odt, .docx, .doc, .pdf och .rtf. Både .odf och .docx är relativt enkla då de båda är zip-filer med xml-innehåll. Vet man bara var man hittar själva innehållet är det enkelt att med hjälp av phps xml-funktioner plocka ut rådatan. Jag fick lite hjälp av följande sida.
Äldre Word-filer i .doc-format löste jag genom att installera paketet antiword (apt-get install antiword på Ubuntu 10.04 Server). Därefter stötte jag på patrull. Tydligen måste Antiword ha en viss path-variabel satt för att inte sparka bakut. Följande löste problemet.
putenv("ANTIWORDHOME=/usr/share/antiword");
echo shell_exec("/usr/bin/antiword /katalog/filnamn.doc");
Pdf-filer löste jag genom pdftotext som är en del av paketet xpdf. pdftotext vill ha två argument varav det andra är den fil man vill skriva till. Ett bindestreck gör att resultatet skickas till stdout.
echo shell_exec("/usr/bin/pdftotext /katalog/filnamn.pdf -");
Det som jag trodde skulle vara enklast men som visade sig lite lurigt var rtf-filer. Jag trodde att jag skulle kunna göra på samma sätt som ovan efter att ha hittat GNU-projektet UnRTF. Vad jag gissar var felet, för jag vet inte säkert, är att unrtf av någon anledning skriver till stderr även vid “framgång”. Detta resulterade i ett elakt 500 internal server error på min Cherokee-server. När jag nästan hade gett upp så hittade jag proc_open i php-manualen. Rent intuitivt kändes det som det kunde vara något att prova. Utan att kunna förklara varför så fungerade nedan utan problem.
$desc = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$proc = proc_open("/usr/bin/unrtf --html /katalog/filnamn.rtf", $desc, $pipes);
echo stream_get_contents($pipes[1]);
$return_value = proc_close($proc);
Att proc_close skulle associeras till en variabel var något som jag också hittade i php-manualen utan att riktigt förstå varför. Eftersom UnRTF enligt egen utsago skulle vara bäst på att skapa html av det extraherade resultatet lät jag den göra det och körde sedan strip_tags och html_entity_decode på resultatet.
Hoppas att detta kan vara till nytta för någon och mig själv i framtiden om jag skulle glömma av det.

