1

I'm trying to use fcimg and wkhtmltoimage in order to export a chart to a PDF report. I keep getting an error from fcimg saying "Fatal error: Uncaught exception 'FCImageException' with message 'There was an error with wkhtmltopdf'[...]".

By debbuging the function inside de fcimg library I've noticed that a couple of 'fwrite()' functions in charge of writing the minified JS scripts of FusionCharts into the file are returning a value of '0' (no writing, but no error), even do the string to write is properly saved into a variable (as the code below). Is there some kind of limit or restrinction to the 'fwrite' function that I'm not aware of? Previous calls to the function work just fine. Any help or advice would be really appreciated.

[...]
function fusioncharts_to_image($outputFilePath, $swfName, $inputString, $height, $width, $options = array())
{

$jsonFlag = false;
if($inputString[0] === '<') // Check for the first character
{
    // do nothing. jsonFlag is set to false anyways
}
else if($inputString[0] === "{")
{
    $jsonFlag = true;
}
else
{
    throw new FCImageException("The input string doesn't seem to be either JSON or XML");
}

$fileType = "png";
if(isset($options['imageType']))
    $fileType = $options['imageType'];

$renderDelay = 1000;
if (isset($options['render_delay']) && is_numeric($options['render_delay']))
    $renderDelay = $options['render_delay'];

/*
 * Note: sys_get_temp_dir returns /tmp on Linux (don't know about osx)
 * but on the other hand, it returns C:\user\foo\Local\Temp\ on Windows
 *
 * so we need to add a directory separator on Linux but not on windows
 */
$separator = "";
if(DIRECTORY_SEPARATOR === "/") // check if unix system. TODO: There will be better ways to do this
    $separator = DIRECTORY_SEPARATOR;

$imageFileName = sys_get_temp_dir().$separator."\FCImage".rand(0, 1000).'.'.$fileType;
// $imageFileName = sys_get_temp_dir().”\FCImage”.rand(0, 1000).’.’.$fileType;
// $imageFileName = 'C:\PRUEBA\FCImage'.rand(0, 1000).'.'.$fileType;


$cwd = __DIR__; // change working directory to the current script's directory
$env = array(); // set any environment variables here

// configure the arguments
$args = "--format $fileType";

$args = $args." --crop-w ".($width - 1);
$args = $args." --crop-h ".($height - 1);

if(isset($options['nodelay']))
{
    if($options['nodelay'] === true)
        $args = $args." --javascript-delay 0";
}
else
{
    $args = $args." --javascript-delay {$renderDelay}";
}



if(isset($options['quality']))
{
    $args = $args." --quality {$options['quality']}";
}

$debugFlag = false;
if(isset($options['debug']))
{
    $debugFlag = true;
    $debugFile = fopen("debug.html", "w");
    echo "\n\nCall to:\n fusioncharts_to_image ($outputFilePath, $swfName, [removing input string], $height, $width)";
}

// now, determine the platform this is running on
$os = php_uname("s");
$arch = php_uname("m");
if($os==="Windows NT"){
    $platform = _FC_IMG_PLATFORM_WINDOWS;
    // var_dump($platform);
}
else if($os === "Linux")
{
    if($arch === "i386")
        $platform = _FC_IMG_PLATFORM_LINUX;
    else if($arch === "i686")
        $platform = _FC_IMG_PLATFORM_LINUX;
    else if ($arch === "x86_64")
        $platform = _FC_IMG_PLATFORM_LINUX_64;
    else
        throw new FCImageException ("This Linux architecture is not supported");
}
else if($os === "Darwin") {
    $platform = _FC_IMG_PLATFORM_OSX;
}
else
    throw new FCImageException("Your server OS is currently not supported");

$fcRoot = dirname(__FILE__);

$wkCommand = $platform;

if(isset($options['wkhtmltoimage_path'])) {
    $wkCommand = $options['wkhtmltoimage_path'];
}
$command = "$wkCommand $args - $imageFileName";
// var_dump($command); echo "<br>";

if($debugFlag)
{
    echo "\n Command: $command";
}

$wkstdin = popen($command, "w");
// var_dump($wkstdin);

if(!is_resource($wkstdin))
{
    throw new FCImageException("An error took place while trying to open wkhtmltopdf");
}

$templateHead = <<<TOP
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title></title>
        <style>
        body{
            padding:0 0 0 0;
            margin:0 0 0 0;
        }
    </style>
    <script>
TOP;

    // ok. write template.txt into the process stdin
    fwrite($wkstdin, $templateHead);

if($debugFlag)
{
    fwrite($debugFile, $templateHead);
}

$contFC = file_get_contents($options['licensed_fusioncharts_js']);
$contFCC = file_get_contents($options['licensed_fusioncharts_charts_js']);
// echo $contFC;
// echo $contFCC;

if(isset($options['licensed_fusioncharts_charts_js']) && isset($options['licensed_fusioncharts_js'])) {

    $temp1 = fwrite($wkstdin, $contFC);
    var_dump($temp1);

    $temp2 = fwrite($wkstdin, $contFCC);
    var_dump($temp2);

    if($debugFlag)
    {
        fwrite($debugFile, file_get_contents($options['licensed_fusioncharts_js']));
    }
    if($debugFlag)
    {
        fwrite($debugFile, file_get_contents($options['licensed_fusioncharts_charts_js']));
    }
}
else {
    throw new FCImageException("Need to provide fusioncharts licensed version here");
}


$functionToCall = "setXMLData";
if($jsonFlag === true)
    $functionToCall = "setJSONData";

// replace all EOL with ""
$escapedData = str_replace("\n", "", $inputString);
$escapedData = addslashes($escapedData);

$templateCode = "</script>
                </head>
                <body>
                <div id='chartContainer'><small>Loading chart...</small></div>
                </body>
                <script>
                FusionCharts.setCurrentRenderer('javascript');
                var chart = new FusionCharts('$swfName', 'chart0', '$width', '$height', '0', '1');
                chart.$functionToCall('$escapedData');
                chart.render('chartContainer');
                </script>
                </html>";
$temp = fwrite($wkstdin, $templateCode);
var_dump($temp);

if($debugFlag)
{
    fwrite($debugFile, $templateCode);
}

$returnCode = pclose($wkstdin);
// echo(var_dump($returnCode)." returnCode");

if($returnCode !== 0)
{
    // var_dump($imageFileName);
    if(file_exists($imageFileName)){
        unlink($imageFileName);
    }
    throw new FCImageException("There was an error with wkhtmltopdf ");
}

// success!
rename($imageFileName, $outputFilePath);

return true;
}
efTobark
  • 11
  • 3
  • 1
    Looking at the [documentation](https://secure.php.net/manual/en/function.fwrite.php#refsect1-function.fwrite-returnvalues), it looks like fwrite will return either FALSE on error or the number of bytes written. Since you got 0 and not false, that could mean it just didn't write anything. Did you check your `$contFC` and `$contFCC` variables? Maybe it has to do with your `file_get_contents` call. – Cave Johnson Jan 31 '17 at 23:16
  • It could be that `$options['licensed_fusioncharts_charts_js']` and `$options['licensed_fusioncharts_charts_js']` are empty (unlikely since you check if they are not null) or that they point to files that don't exist (more likely). – Cave Johnson Jan 31 '17 at 23:23
  • @KodosJohnson Right on the point, but `!isset() || is_null()` != `empty()` – Xorifelse Jan 31 '17 at 23:48
  • Oh yes you are right @Xorifelse. Nevermind what I said. It is still just as likely that those array key values are empty. Anyways, I just realized that you said that you know about the return value of fwrite and the variables have the correct content. So I don't know what is the problem. – Cave Johnson Jan 31 '17 at 23:57
  • @KodosJohnson Don't second guess yourself. `fwrite()` returns false on failure or returns the "*number of bytes written*". Stick with that statement and the only conclusion is that the value to be written is `empty()` according to the `isset()` code. Likely is that with `display_errors` is false and `file_get_contents()` fails returning an empty string. – Xorifelse Feb 01 '17 at 00:25
  • @Xorifelse The OP said "both variables have the correct content to write" so I assume that they echoed the variables and they were not empty. I dunno. Let's see what the OP says if they are still around. – Cave Johnson Feb 01 '17 at 00:29
  • Just as @Xorifelse said, I've checked the variables before the writing and they have the proper values from the JS files, actually if I write anything else in that same 'fwrite' functions, it works with no problem. Any ideas? The files from which I'm retrieving the data are 'fusioncharts.js' and 'fusioncharts.charts.js', as you could see them at www.fusioncharts.com – efTobark Feb 01 '17 at 15:22
  • Could you perhaps add the '*full*' code that '*opens*' the file? is the file `is_writeable()`? – Xorifelse Feb 01 '17 at 15:30
  • There it is @Xorifelse , and yes it should be. As I metioned, if other variable is passed to that same function the writting is done correctly. – efTobark Feb 01 '17 at 17:31

0 Answers0