How to resolve memory size error for large files generated with Dompdf?

Asked

Viewed 1,504 times

4

What happens is that when the HTML (dynamically generated) gets too large, the pdf is not created, and returns this error:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 64 bytes) in /home/www/models/dompdf/include/frame_factory.cls.php on line 51.

This only happens when the HTML file is very large, otherwise it is normally generated. HTML is based on , and has some panels, navtabs etc. Dompdf ignores these tags, but I was wondering if it could not be so...

I’ve tried to some solutions I found in the OS, such as:

ini_set('memory_limit', '-1');

ini_set ( 'memory_limit', '128M');

This I did in the file that generates the PDF, because I do not have access to php.ini, and I don’t know how to do in htaccess (some answers in the OS suggest changing in htaccess if the server allows it)... but nothing has solved so far.

This is the file frame_factory.cls.php (line 51 is marked inside the snippet):

<?php
/**
 * @package dompdf
 * @link    http://www.dompdf.com/
 * @author  Benj Carson <[email protected]>
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 * @version $Id: frame_factory.cls.php 470 2012-02-06 19:36:13Z fabien.menager $
 */

/**
 * Contains frame decorating logic
 *
 * This class is responsible for assigning the correct {@link Frame_Decorator},
 * {@link Positioner}, and {@link Frame_Reflower} objects to {@link Frame}
 * objects.  This is determined primarily by the Frame's display type, but
 * also by the Frame's node's type (e.g. DomElement vs. #text)
 *
 * @access private
 * @package dompdf
 */
class Frame_Factory {

  /**
   * Decorate the root Frame
   * 
   * @param $root Frame The frame to decorate
   * @param $dompdf DOMPDF The dompdf instance
   * @return Page_Frame_Decorator
   */
  static function decorate_root(Frame $root, DOMPDF $dompdf) {
    $frame = new Page_Frame_Decorator($root, $dompdf);
    $frame->set_reflower( new Page_Frame_Reflower($frame) );
    $root->set_decorator($frame);
    return $frame;
  }

  /**
   * Decorate a Frame 
   * 
   * @param $root Frame The frame to decorate
   * @param $dompdf DOMPDF The dompdf instance
   * @return Frame_Decorator
   * FIXME: this is admittedly a little smelly...
   */ 
  static function decorate_frame(Frame $frame, DOMPDF $dompdf) {
    if ( is_null($dompdf) )
      throw new Exception("foo");
      
    $style = $frame->get_style();
    
    switch ($style->display) { */----- LINHA 51 ------- */
      
    case "block":
      $positioner = "Block";        
      $decorator = "Block";
      $reflower = "Block";
      break;
    
    case "inline-block":
      $positioner = "Inline";
      $decorator = "Block";
      $reflower = "Block";
      break;

    case "inline":
      $positioner = "Inline";
      if ( $frame->is_text_node() ) {
        $decorator = "Text";
        $reflower = "Text";
      } 
      else {
        if ( DOMPDF_ENABLE_CSS_FLOAT && $style->float !== "none" ) {
          $decorator = "Block";
          $reflower = "Block";
        }
        else {
          $decorator = "Inline";
          $reflower = "Inline";
        }
      }
      break;   

    case "table":
      $positioner = "Block";
      $decorator = "Table";
      $reflower = "Table";
      break;
      
    case "inline-table":
      $positioner = "Inline";
      $decorator = "Table";
      $reflower = "Table";
      break;

    case "table-row-group":
    case "table-header-group":
    case "table-footer-group":
      $positioner = "Null";
      $decorator = "Table_Row_Group";
      $reflower = "Table_Row_Group";
      break;
      
    case "table-row":
      $positioner = "Null";
      $decorator = "Table_Row";
      $reflower = "Table_Row";
      break;

    case "table-cell":
      $positioner = "Table_Cell";
      $decorator = "Table_Cell";
      $reflower = "Table_Cell";
      break;
        
    case "list-item":
      $positioner = "Block";
      $decorator  = "Block";
      $reflower   = "Block";
      break;

    case "-dompdf-list-bullet":
      if ( $style->list_style_position === "inside" )
        $positioner = "Inline";
      else        
        $positioner = "List_Bullet";

      if ( $style->list_style_image !== "none" )
        $decorator = "List_Bullet_Image";
      else
        $decorator = "List_Bullet";
      
      $reflower = "List_Bullet";
      break;

    case "-dompdf-image":
      $positioner = "Inline";
      $decorator = "Image";
      $reflower = "Image";
      break;
      
    case "-dompdf-br":
      $positioner = "Inline";
      $decorator = "Inline";
      $reflower = "Inline";
      break;

    default:
      // FIXME: should throw some sort of warning or something?
    case "none":
      $positioner = "Null";
      $decorator = "Null";
      $reflower = "Null";
      break;
    }

    // Handle CSS position
    $position = $style->position;
    
    if ( $position === "absolute" )
      $positioner = "Absolute";

    else if ( $position === "fixed" )
      $positioner = "Fixed";
      
    // Handle nodeName
    $node_name = $frame->get_node()->nodeName;
    
    if ( $node_name === "img" ) {
      $style->display = "-dompdf-image";
      $decorator = "Image";
      $reflower = "Image";
    }
  
    $positioner .= "_Positioner";
    $decorator .= "_Frame_Decorator";
    $reflower .= "_Frame_Reflower";

    $deco = new $decorator($frame, $dompdf);
    $deco->set_positioner( new $positioner($deco) );
    $reflow = new $reflower($deco);
    
    $deco->set_reflower( $reflow );
    
    return $deco;
  }
}

  • When this happened to me, I was thinking about the strategy of loading the content on demand (as if it were a pagination) and generating the pdfs in a temporary folder. Then pass the download link, or anything else.

  • I don’t know if I understand @Wallacemaxters... is a single pdf, which is generated through an HTML searched in the bd (the user wrote this HTML in the bd when generated a result, and then caught it with a query sql to put inside the Dompdf template)... You mean to save the pdf before the user’s request, and leave it in a folder right, passing only the link instead of generating at the time of the request... but would it cost less memory? I mean, won’t that be the same problem? Thanks...

  • I already had this same problem when I was going to generate great reports. My solution was to abandon html and even make the layout by hand.

1 answer

2


Note the following, the error informs you that you need more than 134MB of memory to work and the most you set was 128MB. Try to put more memory and check:

ini_set('memory_limit', '256M');

You also need to know if the server supports this setting.

  • So, I tested even with more, I think the problem may be that the server does not even accept... I sent them a message, vms see... +1 Thanks for now.

  • 1

    Okay Gustavo, if shared hosting might not work at all, you would have to go for vps or dedicated. But perhaps they will give an alternative solution. Success!

  • 1

    That’s right (server configuration), and the only way to change is to move to a more expensive plan. :/

Browser other questions tagged

You are not signed in. Login or sign up in order to post.