user470760
user470760

Reputation:

Generated CSV downloads empty but has content

I have written the following script which is to create a CSV file based on content from a Database. The script itself works perfectly and creates the CSV file and populates it as expected. The problem is that when the file downloads automatically it is empty, but when downloading it from the hosting server over FTP it is filled with the information.

Is the file just downloading too soon before the file is successfully written? Is there anything that can be done to fix this issue?

<?php

    // Establish the MySQL Database Connection
    include_once("./include/database.php");
    include("functions.php");

    $filename = 'devices.csv';
    $headers = array('ID', 'Device', 'Name', 'Type', 'Scope', 'OS', 'Datacenter');

    $handle = fopen($filename, 'w');
    fputcsv($handle, $headers, ',', '"');

    $sql = mysql_query("SELECT * FROM devices ORDER BY name ASC", $dp_conn);

    while($results = mysql_fetch_object($sql))
    {
        $type = getDeviceType($results->type, $dp_conn);
        $scope = getDeviceScope($results->scope, $dp_conn);
        $os = getOS($results->os, $dp_conn);
        $datacenter = getDatacenter($results->datacenter, $dp_conn);

        $row = array(
            $results->id,
            $results->device_id,
            $results->name,
            $type,
            $scope['name'],
            $os,
            $datacenter
        );

        fputcsv($handle, $row, ',', '"');
    }

    // rewind the "file" with the csv lines
    fseek($handle, 0);

    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename="' . $filename . '";');

    // make php send the generated csv lines to the browser
    fpassthru($handle);

    fclose($handle);

?>

Upvotes: 0

Views: 1539

Answers (2)

user470760
user470760

Reputation:

After further testing and finding a similar post on the topic, I have found a fix. Rather than using fopen() on a file, I wrote the data to memory and it is now working correctly.

<?php

    // Establish the MySQL Database Connection
    include_once("./include/database.php");
    include("functions.php");

    $filename = 'devices.csv';
    $headers = array('ID', 'Device', 'Name', 'Type', 'Scope', 'OS', 'Datacenter');

    //$handle = fopen($filename, 'w');
    $handle = fopen('php://memory', 'w'); 
    fputcsv($handle, $headers, ',', '"');

    $sql = mysql_query("SELECT * FROM devices ORDER BY name ASC", $dp_conn);

    while($results = mysql_fetch_object($sql))
    {
        $type = getDeviceType($results->type, $dp_conn);
        $scope = getDeviceScope($results->scope, $dp_conn);
        $os = getOS($results->os, $dp_conn);
        $datacenter = getDatacenter($results->datacenter, $dp_conn);

        $row = array(
            $results->id,
            $results->device_id,
            $results->name,
            $type,
            $scope['name'],
            $os,
            $datacenter
        );

        fputcsv($handle, $row, ',', '"');
    }

    // rewind the "file" with the csv lines
    fseek($handle, 0);

    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename="' . $filename . '";');

    // make php send the generated csv lines to the browser
    fpassthru($handle);

    fclose($handle);

?>

Upvotes: 2

justrohu
justrohu

Reputation: 589

try putting this

// Establish the MySQL Database Connection
include_once("./include/database.php");
include("functions.php");

ob_start(); //start output buffering 

$filename = 'devices.csv';
$headers = array('ID', 'Device', 'Name', 'Type', 'Scope', 'OS', 'Datacenter');

$handle = fopen($filename, 'w');
fputcsv($handle, $headers, ',', '"');

$sql = mysql_query("SELECT * FROM devices ORDER BY name ASC", $dp_conn);

while($results = mysql_fetch_object($sql))
{
    $type = getDeviceType($results->type, $dp_conn);
    $scope = getDeviceScope($results->scope, $dp_conn);
    $os = getOS($results->os, $dp_conn);
    $datacenter = getDatacenter($results->datacenter, $dp_conn);

    $row = array(
        $results->id,
        $results->device_id,
        $results->name,
        $type,
        $scope['name'],
        $os,
        $datacenter
    );

    fputcsv($handle, $row, ',', '"');
}

ob_end_clean(); //ending output buffering. 

// rewind the "file" with the csv lines
fseek($handle, 0);

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');

// make php send the generated csv lines to the browser
fpassthru($handle);

fclose($handle);

Upvotes: 0

Related Questions