1

I have installed Print module and also TCPDF library to generate PDF files. However, Print module can just create PDF files to download, but not to save in server folder. I have tried to change method _print_pdf_tcpdf in Print module, so files can be saved in server folder. I have changed _print_pdf_tcpdf function as follows:

I have changed line

$pdf->Output($filename, $output_dest);

to this line:

$pdf->Output($filename, 'F');

But this code throws error:

TCPDF ERROR: Unable to create output file: https://mywebsite/sites/default/files/aaa.pdf

I have set permissions for sites folder to write. Another modules can write into this folder, so I dont think the problem is in permissions. Can anybody help where can be problem?

2
  • Modules should never write to /sites. They should write to /sites/default/files or /sites/example.org/files - so something is wrong with your config, or at least it looks so.
    – Mołot
    Dec 16, 2013 at 8:25
  • Thanks for hint. Saving to files folder does not work, either. I have tried files folder at first, and it didn't work to me. Another modules can write to files folder 9i.e. when saving file uploaded by image field as part of node content). So I don't think itis problem with permissions. Dec 16, 2013 at 9:27

3 Answers 3

3

I've made a couple of TCPDF implementations myself in Drupal. As Clive suggested, you shouldn't use URIs in TCPDF's output() method, instead you'll want to provide absolute filepaths.

This code has always worked for me:

// Change the path to whatever you like, even public:// will do or you could also make use of the private file system by using private://
$path = drupal_realpath('public://folder/folder2/folder3');

// Supply a filename including the .pdf extension
$filename = 'file.pdf';

// Create the full path
$full_path = $path . '/' . $filename;

// Output PDF
$pdf->Output($full_path, 'F');

EDIT: As Clive mentioned in the comment, drupal_realpath() is deprecated. Here's an alternative:

// Change the path to whatever you like, even public:// will do or you could also make use of the private file system by using private://
$uri = 'public://folder/folder2/folder3';
$stream = file_stream_wrapper_get_instance_by_uri($uri);
$path = DRUPAL_ROOT . '/' . $stream->getDirectoryPath() . '/' . file_uri_target($uri);

// Supply a filename including the .pdf extension
$filename = 'file.pdf';

// Create the full path
$full_path = $path . '/' . $filename;

// Output PDF
$pdf->Output($full_path, 'F');

Just make sure you're always providing an absolute path for TCPDF.

2
  • drupal_realpath() shouldn't be used, it's been deprecated. +1 for a working example though
    – Clive
    Dec 16, 2013 at 10:51
  • 1
    Indeed it is. I've added an alternative. Thanks for pointing this out. Dec 16, 2013 at 13:16
2

Looking at the error message

TCPDF ERROR: Unable to create output file: https://mywebsite/sites/default/files/aaa.pdf

It would appear your $filename variable contains a URI, instead of a path. Files can't be saved to URIs; for that to happen you'd need to make an HTTP request with an appropriate verb. So that's likely to be the problem.

I'm not that familiar with TCPDF so I don't know if it support stream wrappers or not. Either of these might therefore work:

$filename = 'public://aaa.pdf';

or

$filename = DRUPAL_ROOT . '/sites/default/aaa.pdf';
-1
$pdf->Output( "myfile.pdf", "F");
TCPDF ERROR: Unable to create output file: myfile.pdf

In the 'include/tcpdf_static.php' file about 2435 line in the static function 'fopenLocal' if I delete the complete 'if statement'... works fine.

public static function fopenLocal($filename, $mode) {

    /*if (strpos($filename, '://') === false) {
        $filename = 'file://'.$filename;
    } elseif (strpos($filename, 'file://') !== 0) {
        return false;
    }*/
    return fopen($filename, $mode);
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.