我在服务器端有一个Struts2操作用于文件下载。

<action name="download" class="com.xxx.DownAction">
    <result name="success" type="stream">
        <param name="contentType">text/plain</param>
        <param name="inputName">imageStream</param>
        <param name="contentDisposition">attachment;filename={fileName}</param>
        <param name="bufferSize">1024</param>
    </result>
</action>

然而,当我使用jQuery调用动作时:

$.post(
  "/download.action",{
    para1:value1,
    para2:value2
    ....
  },function(data){
      console.info(data);
   }
);

在Firebug中,我看到数据是用二进制流检索的。我想知道如何打开文件下载窗口,用户可以在本地保存文件?


当前回答

还有另一种解决方案下载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");

    ...

我希望这个解决方案对很多人都有用,就像对我一样。

其他回答

还有另一种解决方案下载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");

    ...

我希望这个解决方案对很多人都有用,就像对我一样。

这就是它在任何浏览器中都很好(我使用asp.net核心)

function onDownload() { const api = '@Url.Action("myaction", "mycontroller")'; var form = new FormData(document.getElementById('form1')); fetch(api, { body: form, method: "POST"}) .then(resp => resp.blob()) .then(blob => { const url = window.URL.createObjectURL(blob); $('#linkdownload').attr('download', 'Attachement.zip'); $('#linkdownload').attr("href", url); $('#linkdownload') .fadeIn(3000, function() { }); }) .catch(() => alert('An error occurred')); } <button type="button" onclick="onDownload()" class="btn btn-primary btn-sm">Click to Process Files</button> <a role="button" href="#" style="display: none" class="btn btn-sm btn-secondary" id="linkdownload">Click to download Attachments</a> <form asp-controller="mycontroller" asp-action="myaction" id="form1"></form>

        function onDownload() {
            const api = '@Url.Action("myaction", "mycontroller")'; 
            //form1 is your id form, and to get data content of form
            var form = new FormData(document.getElementById('form1'));

            fetch(api, { body: form, method: "POST"})
                .then(resp => resp.blob())
                .then(blob => {
                    const url = window.URL.createObjectURL(blob);
                    $('#linkdownload').attr('download', 'Attachments.zip');
                    $('#linkdownload').attr("href", url);
                    $('#linkdownload')
                        .fadeIn(3000,
                            function() {

                            });
                })
                .catch(() => alert('An error occurred'));                 

        }

让浏览器下载文件的简单方法是像这样发出请求:

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

这将打开浏览器下载弹出。

使用窗口。打开https://developer.mozilla.org/en-US/docs/Web/API/Window/open

例如,你可以把这行代码放在点击处理程序中:

window.open('/file.txt', '_blank');

它将打开一个新选项卡(因为'_blank' window-name),该选项卡将打开URL。

你的服务器端代码也应该是这样的:

res.set('Content-Disposition', 'attachment; filename=file.txt');

通过这种方式,浏览器应该提示用户将文件保存到磁盘,而不仅仅是向他们显示文件。它还会自动关闭刚刚打开的选项卡。

如果服务器在响应中写入文件(包括cookie) 你使用它们来确定文件下载是否开始),简单地创建一个带有值的表单并提交它:

function ajaxPostDownload(url, data) {
    var $form;
    if (($form = $('#download_form')).length === 0) {
        $form = $("<form id='download_form'" + " style='display: none; width: 1px; height: 1px; position: absolute; top: -10000px' method='POST' action='" + url + "'></form>");
        $form.appendTo("body");
    }
    //Clear the form fields
    $form.html("");
    //Create new form fields
    Object.keys(data).forEach(function (key) {
        $form.append("<input type='hidden' name='" + key + "' value='" + data[key] + "'>");
    });
    //Submit the form post
    $form.submit();
}

用法:

ajaxPostDownload('/fileController/ExportFile', {
    DownloadToken: 'newDownloadToken',
    Name: $txtName.val(),
    Type: $txtType.val()
});

控制器方法:

[HttpPost]
public FileResult ExportFile(string DownloadToken, string Name, string Type)
{
    //Set DownloadToken Cookie.
    Response.SetCookie(new HttpCookie("downloadToken", DownloadToken)
    {
        Expires = DateTime.UtcNow.AddDays(1),
        Secure = false
    });

    using (var output = new MemoryStream())
    {
        //get File
        return File(output.ToArray(), "application/vnd.ms-excel", "NewFile.xls");
    }
}