【问题标题】:Download file through an ajax call php通过ajax调用php下载文件
【发布时间】:2011-10-03 20:52:45
【问题描述】:

我有一个按钮,onclick 它将调用一个 ajax 函数。

这是我的 ajax 函数

function csv(){

    ajaxRequest = ajax();//ajax() is function that has all the XML HTTP Requests

    postdata = "data=" + document.getElementById("id").value;

    ajaxRequest.onreadystatechange = function(){
        var ajaxDisplay = document.getElementById('ajaxDiv');
        if(ajaxRequest.readyState == 4 && ajaxRequest.status==200){
            ajaxDisplay.innerHTML = ajaxRequest.responseText;           
        }
    }

    ajaxRequest.open("POST","csv.php",false);
    ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    ajaxRequest.send(postdata);
}

我根据用户输入创建 csv 文件。创建后,我希望它提示下载或强制下载(最好是强制)。我在 php 文件末尾使用以下脚本来下载文件。如果我在单独的文件中运行此脚本,它工作正常。

$fileName = 'file.csv';
$downloadFileName = 'newfile.csv';

if (file_exists($fileName)) {
    header('Content-Description: File Transfer');
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename='.$downloadFileName);
    ob_clean();
    flush();
    readfile($fileName);
    exit;
}
echo "done";

但如果我在 csv.php 的末尾运行它,它会将 file.csv 的内容输出到页面中(到 ajaxDiv 中)而不是下载。

有没有办法强制下载csv.php末尾的文件?

【问题讨论】:

    标签: php javascript ajax download


    【解决方案1】:

    AJAX 不适用于下载文件。弹出一个以下载链接为地址的新窗口,或者document.location = ...

    【讨论】:

    • 我相信技术上最好设置window.location;看到这个讨论:stackoverflow.com/questions/7857878/…
    • 为什么 AJAX 不能用于下载文件?
    • 我无法设置 window.location 因为我需要为我的请求设置一些特殊的标头
    【解决方案2】:

    使用 jQuery 的一个非常简单的解决方案:

    在客户端:

    $('.act_download_statement').click(function(e){
        e.preventDefault();
        form = $('#my_form');
        form.submit();
    });
    

    在服务器端,请确保发回正确的 Content-Type 标头,以便浏览器知道它是附件并开始下载。

    【讨论】:

    • +1 这对我来说非常适合将数据发布到服务器并获取 ZIP 文件下载作为响应。没有页面重新加载。
    • 你能否提供更多细节并提供一些关于两端发生了什么的代码?
    • 代码很好,但是发生了什么错误,它被重定向到一个不需要的错误页面
    • 如果我想暂时展示一些加载器,业务逻辑正在实现和创建文件内容。
    【解决方案3】:

    @joe:非常感谢,这是一个很好的提醒!

    我遇到了一个稍微困难的问题: 1. 发送一个带有POST数据的AJAX请求,让服务器生成一个ZIP文件 2. 得到回复 3.下载ZIP文件

    我就是这样做的(使用 JQuery 处理 AJAX 请求):

    1. 初始发布请求:

      var parameters = {
           pid     : "mypid",
         "files[]": ["file1.jpg","file2.jpg","file3.jpg"]
      }
      
      

      var options = { url: "request/url",//replace with your request url type: "POST",//replace with your request type data: parameters,//see above context: document.body,//replace with your contex success: function(data){ if (data) { if (data.path) { //Create an hidden iframe, with the 'src' attribute set to the created ZIP file. var dlif = $('<iframe/>',{'src':data.path}).hide(); //Append the iFrame to the context this.append(dlif); } else if (data.error) { alert(data.error); } else { alert('Something went wrong'); } } } }; $.ajax(options);

    “request/url”处理 zip 创建(题外话,所以我不会发布完整的代码)并返回以下 JSON 对象。比如:

     //Code to create the zip file
     //......
     //Id of the file
     $zipid = "myzipfile.zip"
     //Download Link - it can be prettier
     $dlink = 'http://'.$_SERVER["SERVER_NAME"].'/request/download&file='.$zipid;
     //JSON response to be handled on the client side
     $result = '{"success":1,"path":"'.$dlink.'","error":null}';
     header('Content-type: application/json;');
     echo $result;
    

    “请求/下载”可以根据需要执行一些安全检查,并生成文件传输:

    $fn = $_GET['file'];
    if ($fn) {
      //Perform security checks
      //.....check user session/role/whatever
      $result = $_SERVER['DOCUMENT_ROOT'].'/path/to/file/'.$fn;
      if (file_exists($result)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename='.basename($result));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($result));
        ob_clean();
        flush();
        readfile($result);
        @unlink($result);
      }
    
    }
    

    【讨论】:

    • 只是 & 需要更改为 ?对于查询字符串。感谢您在这方面的出色帮助! - 我试图进行编辑,但它太小了,它不会让我! $dlink = 'http://'.$_SERVER["SERVER_NAME"].'/request/download?file='.$zipid;
    【解决方案4】:

    我通过隐藏的 iframe 实现了这一点。我使用 perl,而不是 php,所以只会给出概念,而不是代码解决方案。

    客户端向服务器发送 Ajax 请求,导致生成文件内容。这在服务器上保存为临时文件,并将文件名返回给客户端。

    客户端(javascript)接收文件名,并将 iframe src 设置为将传递文件的某个 url,例如:

    $('iframe_dl').src="/app?download=1&filename=" + the_filename
    

    服务器 slurp 文件,取消链接,并将流发送到客户端,带有以下标头:

    Content-Type:'application/force-download'
    Content-Disposition:'attachment; filename=the_filename'
    

    像魅力一样工作。

    【讨论】:

    • “啜饮”是一个技术术语吗?
    【解决方案5】:

    你不能直接通过 ajax 下载文件。

    您可以在页面上放置一个链接,其中包含指向您文件的 URL(从 ajax 调用返回),或者另一种方法是使用隐藏的 iframe 并动态设置该 iframe 的源 URL。这样您就可以在不刷新页面的情况下下载文件。

    这里是代码

    $.ajax({
        url : "yourURL.php",
        type : "GET",
        success : function(data) {
            $("#iframeID").attr('src', 'downloadFileURL');
        }
    });
    

    【讨论】:

    • 发布相关代码将有助于说明您在这里想说的内容。
    • 在您的 ajax 成功响应中,您可以设置隐藏的 iframe src
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多