Download CSV file using “AJAX”

后端 未结 6 1008
感情败类
感情败类 2020-11-29 02:22

I\'m trying to accomplish a fairly simple task for my website, but I\"m not sure exactly how to go about it. I want the user to be viewing a table, then click a button, at w

相关标签:
6条回答
  • 2020-11-29 02:54

    Well the point of using AJAX is to avoid a visible reload of the page. If you want a download, you want the opposite,- a brand new request from the browser. I'd say, just create a simple button pointing to your php page.

    0 讨论(0)
  • 2020-11-29 02:58

    If you are forcing a download, you can redirect the current page to the download link. Since the link will generate a download dialog, the current page (and its state) will be kept in place.

    Basic approach:

    $('a#query_name').click(function(){
        $('#wait-animation').show();
        document.location.href = '/php_scripts/utils/csv_export.php?query_name='+query_name;
        $('#wait-animation').hide();
    });
    

    More complicated:

    $('a#query_name').click(function(){
        MyTimestamp = new Date().getTime(); // Meant to be global var
        $('#wait-animation').show();
        $.get('/php_scripts/utils/csv_export.php','timestamp='+MyTimestamp+'&query_name='query_name,function(){
            document.location.href = '/php_scripts/utils/csv_export.php?timestamp='+MyTimestamp+'&query_name='+query_name;
            $('#wait-animation').hide();
        });
    });
    

    At PHP script:

    @header("Last-Modified: " . @gmdate("D, d M Y H:i:s",$_GET['timestamp']) . " GMT");
    @header("Content-type: text/x-csv");
    // If the file is NOT requested via AJAX, force-download
    if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
        header("Content-Disposition: attachment; filename=search_results.csv");
    }
    //
    //Generate csv
    //
    echo $csvOutput
    exit();
    

    The URL for both requests must be the same to trick the browser not to start a new download at document.location.href, but to save the copy at the cache. I'm not totally sure about it, but seems pretty promising.

    0 讨论(0)
  • 2020-11-29 02:59

    The best way to accomplish this is to use a Data URI as follows:

    1. Make the AJAX call to the server as per normal
    2. Generate the CSV on the server-side
    3. Return the data (either bare or inside a JSON structure)
    4. Create a Data URI in Javascript using the returned data
    5. Set window.location.href to the Data URI

    See this link for instructions (paragraph #3, specifically): http://en.wikipedia.org/wiki/Data_URI_scheme

    This way, you don't need to save any files on the server, and you also don't need to use iframes or hidden form elements or any such hacks.

    0 讨论(0)
  • 2020-11-29 03:04

    I don't think you can make the browser download using a AJAX/JS request. Try using a hidden iframe that navigates to the page which generates the CSV

    0 讨论(0)
  • 2020-11-29 03:11

    EDIT I just tried this with a 10MB file and it seems that val() is too slow to insert the data. Hurrumph.


    Okay, so I gave this one another go. This may or may not be completely insane! The idea is to make an AJAX request to create the data, then use the callback to insert the data into a hidden form on the current page which has an action of a third "download" page; after the insertion, the form is automatically submitted, the download page sends headers and echoes the POST, and et voila, download.

    All the while, on the original page you've got an indication that the file is being prepared, and when it finishes the indicator is updated.

    NOTE: this test code isn't tested extensively, and has no real security checks (or any at all) put in place. I tested it with a 1.5MB CSV file I had laying about and it was reasonably snappy.

    Index.html

    <a id="downloadlink" href="#">Click Me</a>
    <div id="wait"></div>
    <form id="hiddenform" method="POST" action="download.php">
        <input type="hidden" id="filedata" name="data" value="">
    </form>
    

    test.js

    $(document).ready(function(){
      $("#downloadlink").click(function(){       // click the link to download
          lock();                                // start indicator
          $.get("create.php",function(filedata){ // AJAX call returns with CSV file data
              $("#filedata").val(filedata);      // insert into the hidden form
              unlock();                          // update indicator
              $("#hiddenform").submit();         // submit the form data to the download page
          });
      });
    
      function lock(){
          $("#wait").text("Creating File...");
      }
    
      function unlock(){
          $("#wait").text("Done");
      }
    });
    

    create.php

    <?php
    //create $data
    print $data;
    ?>
    

    download.php

    <?php
    header("Pragma: public");
    header("Expires: 0"); 
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Type: text/x-csv");
    header("Content-Disposition: attachment;filename=\"search_results.csv\""); 
    
    if($_POST['data']){
        print $_POST['data'];
    }
    ?>
    
    0 讨论(0)
  • 2020-11-29 03:14

    To echo and expand on what others have said, you can't really send the file using AJAX. One of the reasons for this is (and someone correct me if I'm wrong on this, please) that the page you're currently on already has sent its content headers; you can't send them again to the same window, even with an AJAX request (which is what your PHP file is attempting to do).

    What I've done before in projects is to simply provide a link (with target="_blank" or javascript redirect) to a separate download PHP page. If you're using Apache, check out mod_xsendfile as well.

    0 讨论(0)
提交回复
热议问题