Tema: Pdf y php
Ver Mensaje Individual
  #6 (permalink)  
Antiguo 22/05/2013, 10:54
viringas
 
Fecha de Ingreso: marzo-2011
Mensajes: 226
Antigüedad: 13 años, 1 mes
Puntos: 1
Respuesta: Pdf y php

buscando por internet encontre esta clase PHP que lee un pdf y convierte a texto pero de vez en cuando falla y no hace bien los saltos de linea y mete caracteres raros,

(no se si es porque con los pdfs que trabajo son archivos muy grandes: de mas de 80 paginas)

Código PHP:
Ver original
  1. <?php
  2. class PDF2Text {
  3.     // Some settings
  4.     var $multibyte = 2; // Use setUnicode(TRUE|FALSE)
  5.     var $convertquotes = ENT_QUOTES; // ENT_COMPAT (double-quotes), ENT_QUOTES (Both), ENT_NOQUOTES (None)
  6.    
  7.     // Variables
  8.     var $filename = '';
  9.     var $decodedtext = '';
  10.    
  11.     function setFilename($filename) {
  12.         // Reset
  13.         $this->decodedtext = '';
  14.         $this->filename = $filename;
  15.     }
  16.  
  17.     function output($echo = false) {
  18.         if($echo) echo $this->decodedtext;
  19.         else return $this->decodedtext;
  20.     }
  21.  
  22.     function setUnicode($input) {
  23.         // 4 for unicode. But 2 should work in most cases just fine
  24.         if($input == true) $this->multibyte = 4;
  25.         else $this->multibyte = 2;
  26.     }
  27.  
  28.     function decodePDF() {
  29.         // Read the data from pdf file
  30.         $infile = @file_get_contents($this->filename, FILE_BINARY);
  31.         if (empty($infile))
  32.             return "";
  33.    
  34.         // Get all text data.
  35.         $transformations = array();
  36.         $texts = array();
  37.    
  38.         // Get the list of all objects.
  39.         preg_match_all("#obj[\n|\r](.*)endobj[\n|\r]#ismU", $infile, $objects);
  40.         $objects = @$objects[1];
  41.    
  42.         // Select objects with streams.
  43.         for ($i = 0; $i < count($objects); $i++) {
  44.             $currentObject = $objects[$i];
  45.    
  46.             // Check if an object includes data stream.
  47.             if (preg_match("#stream[\n|\r](.*)endstream[\n|\r]#ismU", $currentObject, $stream)) {
  48.                 $stream = ltrim($stream[1]);
  49.    
  50.                 // Check object parameters and look for text data.
  51.                 $options = $this->getObjectOptions($currentObject);
  52.    
  53.                 if (!(empty($options["Length1"]) && empty($options["Type"]) && empty($options["Subtype"])))
  54.                     continue;
  55.    
  56.                 // Hack, length doesnt always seem to be correct
  57.                 unset($options["Length"]);
  58.    
  59.                 // So, we have text data. Decode it.
  60.                 $data = $this->getDecodedStream($stream, $options);  
  61.    
  62.                 if (strlen($data)) {
  63.                     if (preg_match_all("#BT[\n|\r](.*)ET[\n|\r]#ismU", $data, $textContainers)) {
  64.                         $textContainers = @$textContainers[1];
  65.                         $this->getDirtyTexts($texts, $textContainers);
  66.                     } else
  67.                         $this->getCharTransformations($transformations, $data);
  68.                 }
  69.             }
  70.         }
  71.    
  72.         // Analyze text blocks taking into account character transformations and return results.
  73.         $this->decodedtext = $this->getTextUsingTransformations($texts, $transformations);
  74.     }
  75.  
  76.  
  77.     function decodeAsciiHex($input) {
  78.         $output = "";
  79.    
  80.         $isOdd = true;
  81.         $isComment = false;
  82.    
  83.         for($i = 0, $codeHigh = -1; $i < strlen($input) && $input[$i] != '>'; $i++) {
  84.             $c = $input[$i];
  85.    
  86.             if($isComment) {
  87.                 if ($c == '\r' || $c == '\n')
  88.                     $isComment = false;
  89.                 continue;
  90.             }
  91.    
  92.             switch($c) {
  93.                 case '\0': case '\t': case '\r': case '\f': case '\n': case ' ': break;
  94.                 case '%':
  95.                     $isComment = true;
  96.                 break;
  97.    
  98.                 default:
  99.                     $code = hexdec($c);
  100.                     if($code === 0 && $c != '0')
  101.                         return "";
  102.    
  103.                     if($isOdd)
  104.                         $codeHigh = $code;
  105.                     else
  106.                         $output .= chr($codeHigh * 16 + $code);
  107.    
  108.                     $isOdd = !$isOdd;
  109.                 break;
  110.             }
  111.         }
  112.    
  113.         if($input[$i] != '>')
  114.             return "";
  115.    
  116.         if($isOdd)
  117.             $output .= chr($codeHigh * 16);
  118.    
  119.         return $output;
  120.     }
  121.    
  122.     function decodeAscii85($input) {
  123.         $output = "";
  124.    
  125.         $isComment = false;
  126.         $ords = array();
  127.        
  128.         for($i = 0, $state = 0; $i < strlen($input) && $input[$i] != '~'; $i++) {
  129.             $c = $input[$i];
  130.    
  131.             if($isComment) {
  132.                 if ($c == '\r' || $c == '\n')
  133.                     $isComment = false;
  134.                 continue;
  135.             }
  136.    
  137.             if ($c == '\0' || $c == '\t' || $c == '\r' || $c == '\f' || $c == '\n' || $c == ' ')
  138.                 continue;
  139.             if ($c == '%') {
  140.                 $isComment = true;
  141.                 continue;
  142.             }
  143.             if ($c == 'z' && $state === 0) {
  144.                 $output .= str_repeat(chr(0), 4);
  145.                 continue;
  146.             }
  147.             if ($c < '!' || $c > 'u')
  148.                 return "";
  149.    
  150.             $code = ord($input[$i]) & 0xff;
  151.             $ords[$state++] = $code - ord('!');
  152.    
  153.             if ($state == 5) {
  154.                 $state = 0;
  155.                 for ($sum = 0, $j = 0; $j < 5; $j++)
  156.                     $sum = $sum * 85 + $ords[$j];
  157.                 for ($j = 3; $j >= 0; $j--)
  158.                     $output .= chr($sum >> ($j * 8));
  159.             }
  160.         }
  161.         if ($state === 1)
  162.             return "";
  163.         elseif ($state > 1) {
  164.             for ($i = 0, $sum = 0; $i < $state; $i++)
  165.                 $sum += ($ords[$i] + ($i == $state - 1)) * pow(85, 4 - $i);
  166.             for ($i = 0; $i < $state - 1; $i++)
  167.                 $ouput .= chr($sum >> ((3 - $i) * 8));
  168.         }
  169.    
  170.         return $output;
  171.     }
  172.    
  173.     function decodeFlate($input) {
  174.         return gzuncompress($input);
  175.     }
  176.    
  177.     function getObjectOptions($object) {
  178.         $options = array();
  179.  
  180.         if (preg_match("#<<(.*)>>#ismU", $object, $options)) {
  181.             $options = explode("/", $options[1]);
  182.             @array_shift($options);
  183.    
  184.             $o = array();
  185.             for ($j = 0; $j < @count($options); $j++) {
  186.                 $options[$j] = preg_replace("#\s+#", " ", trim($options[$j]));
  187.                 if (strpos($options[$j], " ") !== false) {
  188.                     $parts = explode(" ", $options[$j]);
  189.                     $o[$parts[0]] = $parts[1];
  190.                 } else
  191.                     $o[$options[$j]] = true;
  192.             }
  193.             $options = $o;
  194.             unset($o);
  195.         }
  196.    
  197.         return $options;
  198.     }
  199.    
  200.     function getDecodedStream($stream, $options) {
  201.         $data = "";
  202.         if (empty($options["Filter"]))
  203.             $data = $stream;
  204.         else {
  205.             $length = !empty($options["Length"]) ? $options["Length"] : strlen($stream);
  206.             $_stream = substr($stream, 0, $length);
  207.    
  208.             foreach ($options as $key => $value) {
  209.                 if ($key == "ASCIIHexDecode")
  210.                     $_stream = $this->decodeAsciiHex($_stream);
  211.                 if ($key == "ASCII85Decode")
  212.                     $_stream = $this->decodeAscii85($_stream);
  213.                 if ($key == "FlateDecode")
  214.                     $_stream = $this->decodeFlate($_stream);
  215.                 if ($key == "Crypt") { // TO DO
  216.                 }
  217.             }
  218.             $data = $_stream;
  219.         }
  220.         return $data;
  221.     }
  222.     function getDirtyTexts(&$texts, $textContainers) {
  223.        
  224.         for ($j = 0; $j < count($textContainers); $j++) {
  225.             if (preg_match_all("#\[(.*)\]\s*TJ[\n|\r]#ismU", $textContainers[$j], $parts))
  226.                 $texts = array_merge($texts, @$parts[1]);
  227.             elseif(preg_match_all("#T[d|w|m|f]\s*(\(.*\))\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts))
  228.                 $texts = array_merge($texts, @$parts[1]);
  229.             elseif(preg_match_all("#T[d|w|m|f]\s*(\[.*\])\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts))
  230.                 $texts = array_merge($texts, @$parts[1]);
  231.         }
  232.     }
  233.     function getCharTransformations(&$transformations, $stream) {
  234.         preg_match_all("#([0-9]+)\s+beginbfchar(.*)endbfchar#ismU", $stream, $chars, PREG_SET_ORDER);
  235.         preg_match_all("#([0-9]+)\s+beginbfrange(.*)endbfrange#ismU", $stream, $ranges, PREG_SET_ORDER);
  236.    
  237.         for ($j = 0; $j < count($chars); $j++) {
  238.             $count = $chars[$j][1];
  239.             $current = explode("\n", trim($chars[$j][2]));
  240.             for ($k = 0; $k < $count && $k < count($current); $k++) {
  241.                 if (preg_match("#<([0-9a-f]{2,4})>\s+<([0-9a-f]{4,512})>#is", trim($current[$k]), $map))
  242.                     $transformations[str_pad($map[1], 4, "0")] = $map[2];
  243.             }
  244.         }
  245.         for ($j = 0; $j < count($ranges); $j++) {
  246.             $count = $ranges[$j][1];
  247.             $current = explode("\n", trim($ranges[$j][2]));
  248.             for ($k = 0; $k < $count && $k < count($current); $k++) {
  249.                 if (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+<([0-9a-f]{4})>#is", trim($current[$k]), $map)) {
  250.                     $from = hexdec($map[1]);
  251.                     $to = hexdec($map[2]);
  252.                     $_from = hexdec($map[3]);
  253.    
  254.                     for ($m = $from, $n = 0; $m <= $to; $m++, $n++)
  255.                         $transformations[sprintf("%04X", $m)] = sprintf("%04X", $_from + $n);
  256.                 } elseif (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+\[(.*)\]#ismU", trim($current[$k]), $map)) {
  257.                     $from = hexdec($map[1]);
  258.                     $to = hexdec($map[2]);
  259.                     $parts = preg_split("#\s+#", trim($map[3]));
  260.                    
  261.                     for ($m = $from, $n = 0; $m <= $to && $n < count($parts); $m++, $n++)
  262.                         $transformations[sprintf("%04X", $m)] = sprintf("%04X", hexdec($parts[$n]));
  263.                 }
  264.             }
  265.         }
  266.     }
  267.     function getTextUsingTransformations($texts, $transformations) {
  268.         $document = "";
  269.         for ($i = 0; $i < count($texts); $i++) {
  270.             $isHex = false;
  271.             $isPlain = false;
  272.    
  273.             $hex = "";
  274.             $plain = "";
  275.             for ($j = 0; $j < strlen($texts[$i]); $j++) {
  276.                 $c = $texts[$i][$j];
  277.                 switch($c) {
  278.                     case "<":
  279.                         $hex = "";
  280.                         $isHex = true;
  281.                     break;
  282.                     case ">":
  283.                         $hexs = str_split($hex, $this->multibyte); // 2 or 4 (UTF8 or ISO)
  284.                         for ($k = 0; $k < count($hexs); $k++) {
  285.                             $chex = str_pad($hexs[$k], 4, "0"); // Add tailing zero
  286.                             if (isset($transformations[$chex]))
  287.                                 $chex = $transformations[$chex];
  288.                             $document .= html_entity_decode("&#x".$chex.";");
  289.                         }
  290.                         $isHex = false;
  291.                     break;
  292.                     case "(":
  293.                         $plain = "";
  294.                         $isPlain = true;
  295.                     break;
  296.                     case ")":
  297.                         $document .= $plain;
  298.                         $isPlain = false;
  299.                     break;
  300.                     case "\\":
  301.                         $c2 = $texts[$i][$j + 1];
  302.                         if (in_array($c2, array("\\", "(", ")"))) $plain .= $c2;
  303.                         elseif ($c2 == "n") $plain .= '\n';
  304.                         elseif ($c2 == "r") $plain .= '\r';
  305.                         elseif ($c2 == "t") $plain .= '\t';
  306.                         elseif ($c2 == "b") $plain .= '\b';
  307.                         elseif ($c2 == "f") $plain .= '\f';
  308.                         elseif ($c2 >= '0' && $c2 <= '9') {
  309.                             $oct = preg_replace("#[^0-9]#", "", substr($texts[$i], $j + 1, 3));
  310.                             $j += strlen($oct) - 1;
  311.                             $plain .= html_entity_decode("&#".octdec($oct).";", $this->convertquotes);
  312.                         }
  313.                         $j++;
  314.                     break;
  315.    
  316.                     default:
  317.                         if ($isHex)
  318.                             $hex .= $c;
  319.                         if ($isPlain)
  320.                             $plain .= $c;
  321.                 break;
  322.                 }
  323.             }
  324.             $document .= "\n";
  325.         }
  326.         return $document;
  327.     }
  328. }
  329. ?>
para visualizar el pdf tenemos que incluir y llamar a la clase tal que asi

Código PHP:
Ver original
  1. include('class.pdf2text.php');
  2. $a = new PDF2Text();
  3. $path = $_SERVER['DOCUMENT_ROOT']."LectorPDF/pdfs/21.pdf";
  4. $a->setFilename($path);
  5. $a->decodePDF();
  6. echo $a->output();

en el echo visualizo el texto por pantalla, lo malo es que cuando llega a algunos saltos de linea (no en todos) decodifica mal y mete caracteres raros. no se a que puede ser debido
si alguien se le da por probarlo y me puede decir si es por culpa de mi equipo o tambien os pasa a vosotros os lo agradezo