简体   繁体   中英

readfile downloads an empty file and wrong file type

I am using the code below to download a csv file from a button click.

JS :

$(document).on("click", "#CSV", function () {

    var csv_value = $('#result').table2CSV({
        delivery: 'value'
    });
    console.log(csv_value);
    $.ajax({
        type: "POST",
        url: "csv.php",
        data: {
            csv: csv_value
        },
        success: function (html) {
             window.location.href = "download.php";
        }
    });

});

csv.php :

require_once ("session_start.php");
if (isset ( $_POST ['csv'] )) {
$file = $_POST['csv'];
$_SESSION ['csvf'] = $file; 
} else {
    echo "No CSV Data";
}

download.php:

session_start();
    $file =$_SESSION['csvf'];
    $filename = $file."_".date("Y-m-d_H-i",time());
    header ( "Content-type: application/vnd.ms-excel" );
    header ( "Content-disposition: filename=" . $filename . ".csv" );
    readfile($filename);
    exit ();

When I execute the function, the file downloaded is download.php despite the correct headers being passed (confirmed via console), the file is also empty. Also when I use print() it prints the CSV data so I know the file isn't empty but it also generates a .php file and prints all the contents inside including the headers. How do I fix this issue?

Edit

I tried brute forcing the download using the following code in .htaccess to no avail.

<FilesMatch "\.(?i:csv)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

The result is still a download.php file.

Try with

Content-Disposition: attachment; filename="<your file name>".

And you have 2 Content-disposition headers (the first one will be overwritten).

The below code worked for me using print() instead of readfile()

session_start ();
$file = $_SESSION ['csvf'];
$_table = $_SESSION['table']; //table Name
$filename =$_table."_".date ( "Y-m-d_H-i", time () ).".csv";  
header ( "Content-type: text/csv" );
header ( "Content-Disposition: attachment; filename=".$filename );
header ( 'Expires: 0' );
header ( 'Cache-Control: must-revalidate' );
header ( 'Pragma: public' );
header ( 'Content-Length: ' . filesize ( $file ) );
print ($file) ;
exit ();

You could simply postfix the script location with the filename you want:

success: function (html) {
     window.location.href = "download.php/something.csv";
}

It will still run download.php but the browser will only see the final part of the URL and treat the download as you would expect.

With this in place you can get rid of your .htaccess hack as well and reduces the php code to:

session_start();
$file =$_SESSION['csvf'];
session_write_close();
readfile($file);

我认为当您尝试下载同一文件的两个副本时,它们会相互抵消

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM