Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用ajax请求下载文件_Javascript_Php_Ajax_File_Download - Fatal编程技术网

Javascript 使用ajax请求下载文件

Javascript 使用ajax请求下载文件,javascript,php,ajax,file,download,Javascript,Php,Ajax,File,Download,我想在单击按钮时发送一个“ajax下载请求”,因此我尝试了以下方法: javascript: var xhr = new XMLHttpRequest(); xhr.open("GET", "download.php"); xhr.send(); 下载.php: <? header("Cache-Control: public"); header("Content-Description: File Transfer"); header("Content-Disposition: att

我想在单击按钮时发送一个“ajax下载请求”,因此我尝试了以下方法:

javascript:

var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();
下载.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");
?>


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

2015年4月27日更新

HTML5场景中出现的是。它在Firefox和Chrome中,很快就会出现在IE11中。根据您的需要,您可以使用它来代替AJAX请求(或使用
window.location
),只要您要下载的文件与您的站点位于同一来源

通过使用测试是否支持
下载
,您始终可以将AJAX请求/
窗口.位置
设为备用,如果不支持,则将其切换为调用
窗口.位置

原始答案

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

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

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

实际上,您根本不需要AJAX。如果您只是将“download.php”设置为按钮上的href,或者,如果不是链接,请使用:

window.location = 'download.php';

浏览器应该识别二进制下载,而不是加载实际页面,而只是将文件作为下载来使用。

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

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

window.location="download.php?filename=export.csv";
<?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);

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

window.location="download.php?filename=export.csv";
<?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);

?>

我更喜欢
location.assign(url)

完整语法示例:

document.location.assign('https://www.urltodocument.com/document.pdf');

要让浏览器下载文件,您需要这样请求:

 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();
 }

从文件头解码文件名有点复杂

    var filename = "default.pdf";
    var disposition = req.getResponseHeader('Content-Disposition');

    if (disposition && disposition.indexOf('attachment') !== -1) 
    {
       var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
       var matches = filenameRegex.exec(disposition);

       if (matches != null && matches[1]) 
           filename = matches[1].replace(/['"]/g, '');
    }

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

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

<a id="target" style="display: none"></a>

这个解决方案与上面的解决方案没有太大区别,但对我来说,它工作得很好,而且我认为它很干净

我建议对文件服务器端进行base64编码(base64_encode(),如果您使用的是PHP),并将base64编码的数据发送到客户端

在客户端上,您可以执行以下操作:

 let blob = this.dataURItoBlob(THE_MIME_TYPE + "," + response.file);
 let uri = URL.createObjectURL(blob);
 let link = document.createElement("a");
 link.download = THE_FILE_NAME,
 link.href = uri;
 document.body.appendChild(link);
 link.click();
 document.body.removeChild(link);
此代码将编码的数据放入链接中,模拟单击链接,然后将其删除。

您的需求将由
window.location('download.php')
但是我认为您需要传递要下载的文件,而不是总是下载同一个文件,这就是为什么要使用请求,一个选项是创建一个像showfile.php这样简单的php文件,并执行如下请求

var myfile = filetodownload.txt
var url = "shofile.php?file=" + myfile ;
ajaxRequest.open("GET", url, true);
showfile.php

<?php
$file = $_GET["file"] 
echo $file;

还有另一种在ajax中下载网页的解决方案。但我指的是一个必须先处理然后下载的页面

首先,您需要将页面处理与结果下载分开

1) ajax调用中只进行页面计算

$.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" }, function(data, status) { if (status == "success") { /* 2) In the answer the page that uses the previous calculations is downloaded. For example, this can be a page that prints the results of a table calculated in the ajax call. */ window.location.href = DownloadPage.php+"?ID="+29; } } ); // For example: in the CalculusPage.php if ( !empty($_POST["calculusFunction"]) ) { $ID = $_POST["ID"]; $query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$_POST["data1"]."', '".$_POST["data2"]."') WHERE id = ".$ID; ... } // For example: in the DownloadPage.php $ID = $_GET["ID"]; $sede = "SELECT * FROM ExamplePage WHERE id = ".$ID; ... $filename="Export_Data.xls"; header("Content-Type: application/vnd.ms-excel"); header("Content-Disposition: inline; filename=$filename"); ... $.post(“CalculusPage.php”,{calculusFunction:true,ID:29,data1:a,data2:b}, 功能(数据、状态) { 如果(状态=“成功”) { /*2)在回答中,将下载使用先前计算的页面。例如,这可以是一个打印在ajax调用中计算的表的结果的页面*/ window.location.href=DownloadPage.php+“?ID=“+29; } } ); //例如:在CalculusPage.php中 如果(!empty($\u POST[“calculusFunction”])) { $ID=$_POST[“ID”]; $query=“插入示例页面(数据1,数据2)值(‘“$\u POST[“数据1”]。‘,‘“$\u POST[“数据2”]。”),其中id=“.id; ... } //例如:在DownloadPage.php中 $ID=$_GET[“ID”]; $sede=“从示例页面中选择*,其中id=”.$id; ... $filename=“Export_Data.xls”; 标题(“内容类型:application/vnd.ms excel”); 标题(“内容配置:内联;文件名=$filename”); ...
我希望这个解决方案能像对我一样对许多人有用。

对于那些寻求更现代方法的人,您可以使用
获取API
。以下示例显示如何下载电子表格文件。使用以下代码很容易完成

fetch(url, {
    body: JSON.stringify(data),
    method: 'POST',
    headers: {
        'Content-Type': 'application/json; charset=utf-8'
    },
})
.then(response => response.blob())
.then(response => {
    const blob = new Blob([response], {type: 'application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
    const downloadUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = downloadUrl;
    a.download = "file.xlsx";
    document.body.appendChild(a);
    a.click();
})
我相信这种方法比其他
XMLHttpRequest
解决方案更容易理解。此外,它的语法与
jQuery
方法类似,无需添加任何附加库

当然,我建议您检查您正在开发的浏览器,因为这种新方法在IE上不起作用。您可以在下面找到完整的浏览器兼容性列表


重要:在本例中,我向侦听给定
url的服务器发送一个JSON请求。这个
url
必须设置,在我的示例中,我假设您知道这一部分。此外,还要考虑您的请求所需的报头。因为我要发送一个JSON,所以我必须添加
Content-Type
头并将其设置为
application/JSON;charset=utf-8,以便让服务器知道它将接收的请求类型。

@Joao Marcos解决方案适合我,但我必须修改代码使其在IE上工作,如果代码看起来像下面的代码

       downloadFile(url,filename) {
        var that = this;
        const extension =  url.split('/').pop().split('?')[0].split('.').pop();

        var req = new XMLHttpRequest();
        req.open("GET", url, true);
        req.responseType = "blob";
        req.onload = function (event) {
            const fileName = `${filename}.${extension}`;
            const blob = req.response;

            if (window.navigator.msSaveBlob) { // IE
                window.navigator.msSaveOrOpenBlob(blob, fileName);
            } 
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);                
            link.download = fileName;
            link.click();
            URL.revokeObjectURL(link.href);

        };

        req.send();
    },
这对我有用

var dataObj = {
somekey:"someValue"
}
     $.ajax({
        method: "POST",
        url: "/someController/someMethod",
        data: dataObj,
        success: function (response) {
            const blob = new Blob([response], { type: 'text/csv' });
            const downloadUrl = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.href = downloadUrl;
            a.download = "file.csv";
            document.body.appendChild(a);
            a.click();
        }
    });

这是行不通的,见[这个问题][1]。[1] :Do
location.href='download.php'当你需要的时候试试这个,它确实让你觉得这是一件普通的事情,可惜没有优雅的解决方案。你用来更改
窗口的编程语言。位置
是JavaScript。你是对的@mi
var dataObj = {
somekey:"someValue"
}
     $.ajax({
        method: "POST",
        url: "/someController/someMethod",
        data: dataObj,
        success: function (response) {
            const blob = new Blob([response], { type: 'text/csv' });
            const downloadUrl = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.href = downloadUrl;
            a.download = "file.csv";
            document.body.appendChild(a);
            a.click();
        }
    });