简体   繁体   中英

Download file with ajax and php - readfile not working

I want to save a value to a txt-file and download it to the user.

Right now, the value is being printed into the txt-file correctly, but the readfile function is not triggered, thus no downloading begins.

The php, this code is located on the same page as the ajax call.

<?php 
if (isset($_POST['data']))
{
$handle = fopen("file.txt", "w");
fwrite($handle, $_POST['data']);
fclose($handle);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename('file.txt'));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('file.txt'));
readfile('file.txt');    
exit;   

}

?>

The javascript, there is no url because the data is to be sent to the current page.

 function exportColors() {        
    var exportData = this.dataset.id;

    $.ajax({
            type: "POST",
            data: {data: exportData},
            success: function (data) {
               console.log(data);   
            }   
        });


}

You need to separate the functionality, that is, post the data to PHP first, save the content of the text file and then, in a second request, let the user download the file. So one (skeleton) approach would be:

JS File:

function exportColors() {        
    var exportData = this.dataset.id;

    $.ajax({
        type: "POST",
        data: {data: exportData},
        success: function (data) {
            // redirect or print out a link
        }   
    });

}

PHP File for the first request (saving the content):

<?php 
if (isset($_POST['data'])) {
    $handle = fopen("file.txt", "w");
    fwrite($handle, $_POST['data']);
    fclose($handle);
    // give back some unique id or the unique filepath
}
?>

PHP File for the second request (be it through clicking on a link or after having been redirected):

// essentially everything that outputs your file
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename('file.txt'));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('file.txt'));
readfile('file.txt');    
exit;   

Comments: Either give back a unique filepath or via a handle through a database (more secure, but more complex as well). Besides, why should the user download the unchanged data he has formerly submitted? Is there more to it than meets the eye?

Ok I'm going out on a limb so take this with a grain of salt.

You said this request is going to the current page? Does that mean you've excluded (for the sake of brevity) HTML content from the PHP file you're showing us? If you have ANY content above your opening <?php tag, then any call to header will fail with an error (because headers must come before the body of a request). This would cause the script to terminate and prevent the readfile line from ever being reached.

Are your headers being sent? Do you see anything in the error log? If the answers to these are yes and no respectively then I'm wrong and you can ignore this.

Due to security reasons, ajax won't be able to download/save the file to the client's system because of java-script constraints.

Instead you can use

jquery.fileDownload.js

Please have a look at http://jqueryfiledownload.apphb.com/

Hope this helps.

you can't

beacuse javascript is not able to write on user file system.

see answer

Download a file by jQuery.Ajax

explain problem very well

The following Ajax generates a new file on the server at runtime AND downloads it to the client machine's /downloads directory with a single click. It uses Javascript to download the file, not PHP readfile().

 await $.ajax("generateFile.php", {
     type: "POST",
     data: {
        param_1: param_1,
        param_2: param_2
    },        
    success: function(data){
        var a = $("<a>")
            .attr("href", "path/filename_on_server.txt")
            .attr("download", "filename_on_client.txt")
            .appendTo("body");
        a[0].click();
        a.remove();
        },
    error : function(data) {
            alert("ajax error, json: " + data);
    }
});

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