我在服务器端有一个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中,我看到数据是用二进制流检索的。我想知道如何打开文件下载窗口,用户可以在本地保存文件?


当前回答

在上面添加一些东西来下载文件

下面是一些生成字节数组的java spring代码

@RequestMapping(value = "/downloadReport", method = { RequestMethod.POST })
    public ResponseEntity<byte[]> downloadReport(
            @RequestBody final SomeObejct obj, HttpServletResponse response) throws Exception {

        OutputStream out = new ByteArrayOutputStream();
        // write something to output stream
        HttpHeaders respHeaders = new HttpHeaders();
        respHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        respHeaders.add("X-File-Name", name);
        ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
        return new ResponseEntity<byte[]>(bos.toByteArray(), respHeaders, HttpStatus.CREATED);
    }

现在在javascript代码中使用filesver .js,可以下载带有下面代码的文件

var json=angular.toJson("somejsobject");
var url=apiEndPoint+'some url';
var xhr = new XMLHttpRequest();
//headers('X-File-Name')
xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 201) {
        var res = this.response;
        var fileName=this.getResponseHeader('X-File-Name');
        var data = new Blob([res]);
        saveAs(data, fileName); //this from FileSaver.js
    }
}    
xhr.open('POST', url);
xhr.setRequestHeader('Authorization','Bearer ' + token);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = 'arraybuffer';
xhr.send(json);

以上将下载文件

其他回答

没有人贴出这个@Pekka的解决方案…所以我会把它贴出来。它可以帮助别人。

您不需要通过Ajax来实现这一点。只使用

window.location="download.action?para1=value1...."

这就是它在任何浏览器中都很好(我使用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'));                 

        }

我为这个问题挣扎了很长一段时间。最后,这里建议的一个优雅的外部库帮助了我。

我尝试下载一个CSV文件,然后在下载完成后做一些事情。所以我需要实现一个适当的回调函数。

使用window.location="…"不是一个好主意,因为下载完成后我无法操作该程序。像这样,改变头,所以这不是一个好主意。

fetch是一个很好的选择,但是它不支持ie11。window.URL.createObjectURL不支持ie11。你可以参考这个。

这是我的密码,它类似于沙赫鲁克·阿拉姆的密码。但你应该注意window。url。createobjecturl可能会造成内存泄漏。你可以参考这个。当响应到达时,数据将被存储到浏览器的内存中。因此,在单击链接之前,文件已经下载。这意味着下载后你可以做任何事情。

$.ajax({
    url: 'your download url',
    type: 'GET',
}).done(function (data, textStatus, request) {
    // csv => Blob
    var blob = new Blob([data]);

    // the file name from server.
    var fileName = request.getResponseHeader('fileName');

    if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE
    window.navigator.msSaveOrOpenBlob(blob, fileName);
    } else { // for others
    var url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.style.display = 'none';
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);

    //Do something after download 
    ...

    }
}).then(after_download)
}
function downloadURI(uri, name) 
{
    var link = document.createElement("a");
    link.download = name;
    link.href = uri;
    link.click();
}