使用ajax请求下载文件

Man*_*rio 87 javascript php ajax file download

我想点击按钮时发送"ajax下载请求",所以我试着这样做:

JavaScript的:

var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();
Run Code Online (Sandbox Code Playgroud)

的download.php:

<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");    
readfile("file.txt");
?>
Run Code Online (Sandbox Code Playgroud)

但是没有按预期工作,我该怎么办?先感谢您

Ste*_*ert 86

2015年4月27日更新

下载属性是HTML5场景.它在Firefox和Chrome中得到支持,很快就会进入IE11.根据您的需要,您可以使用它而不是AJAX请求(或使用window.location),只要您要下载的文件与您的站点位于同一源.

你总是可以window.location通过使用一些JavaScript来测试是否download支持AJAX请求/ 回退,如果不支持,则将其切换为调用window.location.

原始答案

您不能让AJAX请求打开下载提示,因为您必须导航到该文件以提示下载.相反,您可以使用成功函数导航到download.php.这将打开下载提示,但不会更改当前页面.

$.ajax({
    url: 'download.php',
    type: 'POST',
    success: function() {
        window.location = 'download.php';
    }
});
Run Code Online (Sandbox Code Playgroud)

尽管这回答了这个问题,但最好只使用window.location并完全避免AJAX请求.

  • 这不是两次调用链接吗?我在类似的船上......我在标题中传递了很多安全信息,并且能够在成功函数中解析文件对象,但不知道如何触发下载提示. (38认同)
  • 这没有任何意义,为什么它会被投票? (22认同)
  • 但是它会发送2次请求,这是不合适的 (3认同)
  • 它确实会两次调用该页面,因此,如果您要查询该页面中的数据库,则意味着有2次访问DB。 (2认同)
  • 让我解释一下这对我有什么帮助......这个例子本来可以更完整。与“download.php?get_file = true”或其他...我有一个ajax函数,可以对表单提交进行一些错误检查,然后创建一个csv文件。如果错误检查失败,它必须返回失败的原因。如果它创建 CSV,它会告诉父级“继续获取文件”。我通过使用表单变量发布到 ajax 文件,然后将不同的参数发布到同一文件,表示“将您刚刚创建的文件交给我”(路径/名称硬编码到 ajax 文件中)来实现这一点。 (2认同)

Jel*_*alt 42

实际上你根本不需要ajax.如果您只是将"download.php"设置为按钮上的href,或者,如果它不是链接,则使用:

window.location = 'download.php';
Run Code Online (Sandbox Code Playgroud)

浏览器应该识别二进制下载而不加载实际页面,而只是作为下载文件提供.

  • 您用来更改`window.location`*的编程语言是*JavaScript. (3认同)
  • 你是对的@mikemaccana,我实际上指的是ajax:)。 (2认同)
  • 一直在寻找解决方案,这是如此的优雅和完美。非常感谢。 (2认同)
  • 当然,这个解决方案只有在它是一个已经存在的静态文件时才有效。 (2认同)
  • 如果服务器以错误响应,尽管浏览器将无法在没有重定向到错误页面的情况下停留在您的主页上。至少当 window.location 的结果返回 404 时,Chrome 是这样做的。 (2认同)

Joã*_*cos 35

要使浏览器下载文件,您需要发出以下请求:

 function downloadFile(urlToSend) {
     var req = new XMLHttpRequest();
     req.open("GET", urlToSend, true);
     req.responseType = "blob";
     req.onload = function (event) {
         var blob = req.response;
         var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
         var link=document.createElement('a');
         link.href=window.URL.createObjectURL(blob);
         link.download=fileName;
         link.click();
     };

     req.send();
 }
Run Code Online (Sandbox Code Playgroud)

  • 这适用于我,但在firefox中,我需要先在DOM中添加一个<a>标签,并将其作为我的链接引用,而不是动态创建一个,以便自动下载文件. (7认同)

leo*_*leo 16

跨浏览器解决方案,在Chrome,Firefox,Edge,IE11上测试.

在DOM中,添加隐藏的链接标记:

<a id="target" style="display: none"></a>
Run Code Online (Sandbox Code Playgroud)

然后:

var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.setRequestHeader('my-custom-header', 'custom-value'); // adding some headers (if needed)

req.onload = function (event) {
  var blob = req.response;
  var fileName = null;
  var contentType = req.getResponseHeader("content-type");

  // IE/EDGE seems not returning some response header
  if (req.getResponseHeader("content-disposition")) {
    var contentDisposition = req.getResponseHeader("content-disposition");
    fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
  } else {
    fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
  }

  if (window.navigator.msSaveOrOpenBlob) {
    // Internet Explorer
    window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
  } else {
    var el = document.getElementById("target");
    el.href = window.URL.createObjectURL(blob);
    el.download = fileName;
    el.click();
  }
};
req.send();
Run Code Online (Sandbox Code Playgroud)


Ped*_*usa 14

有可能的.您可以从ajax函数内部开始下载,例如,在创建.csv文件之后.

我有一个ajax函数,可以将联系人数据库导出到.csv文件,在完成后,它会自动启动.csv文件下载.所以,在我得到responseText并且一切正常后,我重定向浏览器,如下所示:

window.location="download.php?filename=export.csv";
Run Code Online (Sandbox Code Playgroud)

我的download.php文件如下所示:

<?php

    $file = $_GET['filename'];

    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: attachment; filename=".$file."");
    header("Content-Transfer-Encoding: binary");
    header("Content-Type: binary/octet-stream");
    readfile($file);

?>
Run Code Online (Sandbox Code Playgroud)

没有页面刷新,文件自动开始下载.

- 在以下浏览器中测试过:

Chrome v37.0.2062.120 
Firefox v32.0.1
Opera v12.17
Internet Explorer v11
Run Code Online (Sandbox Code Playgroud)

  • @PedroSousa ..没有.htaccess控制通过Apache访问文件结构.由于访问已经到达PHP脚本,htaccess现在停止了它的职责.这确实是一个安全漏洞,因为确实,PHP(以及它正在运行的用户)可以读取的任何文件,因此它可以传递到readfile ...应该始终清理要读取的请求文件 (9认同)
  • 我想是的,因为任何人都可以调用download.php?filename = [something]并尝试一些路径和文件名,特别是常见的名称,这甚至可以在程序或脚本中的循环内完成. (5认同)