我有一个javascript应用程序,发送ajax POST请求到某个URL。Response可以是JSON字符串,也可以是文件(作为附件)。我可以很容易地在ajax调用中检测到Content-Type和Content-Disposition,但是一旦我检测到响应包含一个文件,我如何让客户端下载它呢?我在这里读过一些类似的帖子,但没有一个能提供我想要的答案。

请,请,请不要发布建议我不应该使用ajax或我应该重定向浏览器的答案,因为这些都不是一个选项。使用普通的HTML表单也是不可行的。我所需要的是向客户端显示一个下载对话框。这能做到吗?如何做到?


当前回答

我是这么做的 https://stackoverflow.com/a/27563953/2845977

. ajax({美元 url: ' < URL_TO_FILE >”, 成功:函数(数据){ var blob=new blob ([data]); var链接= document.createElement (' a '); link.href = window.URL.createObjectURL (blob); link.download = " < FILENAME_TO_SAVE_WITH_EXTENSION >”; link.click (); } });

使用download.js更新答案

. ajax({美元 url: ' < URL_TO_FILE >”, 成功:下载。绑定(true, "<FILENAME_TO_SAVE_WITH_EXTENSION>", "<FILE_MIME_TYPE>") });

其他回答

我想指出在接受的答案中使用这种技术时出现的一些困难,即使用表单post:

You can't set headers on the request. If your authentication schema involves headers, a Json-Web-Token passed in the Authorization header, you'll have to find other way to send it, for example as a query parameter. You can't really tell when the request has finished. Well, you can use a cookie that gets set on response, as done by jquery.fileDownload, but it's FAR from perfect. It won't work for concurrent requests and it will break if a response never arrives. If the server responds with a error, the user will be redirected to the error page. You can only use the content types supported by a form. Which means you can't use JSON.

我最终使用在S3上保存文件并发送预签名URL来获取文件的方法。

下面是我使用临时隐藏表单的解决方案。

//Create an hidden form
var form = $('<form>', {'method': 'POST', 'action': this.href}).hide();

//Add params
var params = { ...your params... };
$.each(params, function (k, v) {
    form.append($('<input>', {'type': 'hidden', 'name': k, 'value': v}));
});

//Make it part of the document and submit
$('body').append(form);
form.submit();

//Clean up
form.remove();

注意,我大量使用JQuery,但你可以用原生JS做同样的事情。

如果response是一个数组缓冲区,在Ajax的onsuccess事件下尝试这个:

 if (event.data instanceof ArrayBuffer) {
          var binary = '';
          var bytes = new Uint8Array(event.data);
          for (var i = 0; i < bytes.byteLength; i++) {
              binary += String.fromCharCode(bytes[i])
          }
          $("#some_id").append("<li><img src=\"data:image/png;base64," + window.btoa(binary) + "\"/></span></li>");
          return;
      }

事件的地方。数据是XHR事件成功函数接收到的响应。

我使用了Naren Yellavula的解决方案,并在使用jquery尝试其他几个解决方案后,对脚本进行了很少的更改。但是,jquery将不能正确下载zip文件。下载后我无法解压缩文件。 在我的用例中,我必须上传一个压缩文件,该文件在Servlet中解压缩,在压缩文件下载到客户端之前,文件被处理并再次压缩。这是你在客户端需要做的事情。

$('#fileUpBtn').click(function (e){ e.preventDefault(); var file = $('#fileUpload')[0].files[0]; var formdata = new FormData(); formdata.append('file', file); // Use XMLHttpRequest instead of Jquery $ajax to download zip files xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var a = document.createElement('a'); a.href = window.URL.createObjectURL(xhttp.response); a.download = "modified_" + file.name; a.style.display = 'none'; document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(a.href); } }; xhttp.open("POST", "<URL to Servlet>", true); xhttp.responseType = 'blob'; xhttp.send(formdata); }); <div class="form-group"> <label id="fileUpLabel" for="fileUpload"></label> <input type="file" class="form-control" id="fileUpload" name="file" accept="" required/> </div> <button class="btn" type="submit" id="fileUpBtn"></button>

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

    ...

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