PHP -引导模式对话框,选择日期,下载CSV -不能让浏览器保存文件


PHP - Bootstrap modal dialog, pick date, download CSV - can't get browser to save the file

我使用Bootstrap来显示一个页面,其中一些是数据的提取。我添加了一个下载按钮,它会弹出一个模态对话框,包括一个日期范围选择器,一个关闭和下载按钮,允许下载更大范围的数据。

Modal代码的摘录:

          <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h3 class="modal-title" id="DownloadModalLabel">Download Data </h3>
      </div>
      <div class="modal-body">
        <form id="download_form" action="api-dl.php" method="get">
          <div class="form-group">
            <label for="channel-name" class="control-label">Download Period:</label>
            <input type="text" name="daterange" value="<?php echo $DownloadDateStart . " - " . $DownloadDateEnd; ?>" />
          </div>
          <div class="form-group hidden">
            <input type="text" id="channel-id" name="channel-id" class="channel-id" value="ha" />
            <input type="text" name="site-id" class="site-id" value="<?php echo $SITE; ?>" />
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" id="submitForm" class="btn btn-primary" data-dismiss="modal">Download CSV</button>
      </div>

下面有一个响应提交按钮的脚本:

    $(document).ready(function () {
      $("#download_form").on("submit", function(e) {
        var postData = $(this).serializeArray();
        var formURL = $(this).attr("action");
        $.ajax({
          url: formURL,
          type: "GET",
          data: postData,
        });
      e.preventDefault();
      });
      $("#submitForm").on('click', function() {
        $("#download_form").submit();
      });
    });

您将注意到,我调用一个php文件"api-dl.php"来提取数据并使用CSV文件进行响应。缩减到最少的一行响应,文件看起来像:

header('Content-Disposition: attachment; filename="12345678.csv";');
header('Content-Type: "text/csv"');
header("Content-Length: 32");
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
header("Expires: 0");
//
echo '"15/10/2016", "12:00", "1.234'n"';
在这一点上,我已经尝试了大量的刷新和输出到php输出流等。我总是进入浏览器的检查面板

请求头:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Cookie:PHPSESSID=.....
Host:r ....  .net.au
Referer:http://r ....  .net.au/site.php?region=Test&site=Test
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.90 Safari/537.36 Vivaldi/1.4.589.11
X-Requested-With:XMLHttpRequest

响应标头:

Cache-Control:no-cache, no-store, must-revalidate
Connection:Keep-Alive
Content-Disposition:attachment; filename="12345678.csv";
Content-Length:32
Content-Type:"text/csv"
Date:Sat, 24 Sep 2016 00:53:13 GMT
Expires:0
Keep-Alive:timeout=5, max=100
Pragma:no-cache
Server:Apache/2.4.18 (Ubuntu)

在我看来,这看起来是对的,我已经尝试了1248个关于这个主题的变化。在"响应"选项卡中,我看到了我期望的响应:

"15/10/2016", "12:00", "-1.234"

但是无论如何我也不能让浏览器下载它。

我看到一些Javascript看起来不错,但数据在客户端不可用,它在服务器上的数据库。

我想我不会错过太多——你觉得会是什么呢?

这很好。强制下载时,可以将当前页面重定向到下载链接。参考:使用"AJAX"下载CSV文件

<script type="text/javascript">
$(document).ready(function () {
    $("#download_form").on("submit", function(e) {
        $('#wait-animation').show(); /* If required show animation */
        var postData = $(this).serializeArray();
        var site_id = $('.site-id').val();  
        var channel_id = $('.channel-id').val();            
        var daterange = $('.daterange').val();      
        document.location.href = $(this).attr("action")+"?site_id"+site_id+"&daterange="+daterange;
        /*e.preventDefault();*/
        $('#wait-animation').hide(); /* hide animation after download completes*/
  });
  $("#submitForm").on('click', function() {
    $("#download_form").submit();
  });
});
</script>

XHR无法处理下载。浏览器不支持这样的解决方案。请在api-dl.php文件中更改您的响应,并返回那里只有一个下载链接。接下来,ajax看起来像这样:

$.ajax({
    url: formURL,
    type: "GET",
    data: postData,
    success: function(response){
        window.open(response);
    }
});
之后你会看到浏览器是如何下载文件的

我几乎做了同样的事情,但尝试在触发下载的php文件的头字符串末尾附加readfile。例子:

<?php
$file = "http://path_to_some_file.csv;
header('Content-Type: text/csv; charset=utf-8');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename="any_name_of_file.csv");
readfile($file);
?>