Spring Rest和jQuery Ajax文件下载

3
我目前正在使用jQuery和Spring Rest。 jQuery用于将文件上传和下载到服务器。上传过程正常,但我在下载文件方面遇到了一些小问题。因此,情景是这样的,在视图中,用户将选择要下载的n个文件并单击下载按钮。一旦用户点击该按钮,文件将被下载。我不想为每个文件下载打开一个新标签页。我想在同一窗口中下载而不刷新当前视图。我查看了这里,但没有帮助我很多。有什么方法可以实现这一点吗?
2个回答

2

这是我下载文件的解决方案:

Spring控制器方法:

@RequestMapping(value = "/download", method = RequestMethod.GET)
public void retrieveDocument(@RequestParam("id") String id, HttpServletResponse response) throws IOException {
    InputStream in = fileService.getFileStream(); // My service to get the stream.
    response.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    response.setHeader("Content-Transfer-Encoding", "binary");
    response.setHeader("Content-Disposition", "attachment; filename=" + filename);
    try {
        IOUtils.copy(inputStream, response.getOuputStream()); //Apache commons IO.
        inputStream.close();
        response.flushBuffer();
        response.setStatus(HttpServletResponse.SC_OK);
    } catch (Exception e) {
        //log error.
    }

在客户端的函数:

function download(id) {
    var id = $('#file').attr('id')
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'url here' + id, true);
    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {
        if(this.status == '200') {
           var filename = '';
           //get the filename from the header.
           var disposition = xhr.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, '');
           }
           var type = xhr.getResponseHeader('Content-Type');
           var blob = new Blob([this.response],  {type: type});
           //workaround for IE
           if(typeof window.navigator.msSaveBlob != 'undefined') {
               window.navigator.msSaveBlob(blob, filename);
           }
           else {
               var URL = window.URL || window.webkitURL;
               var download_URL = URL.createObjectURL(blob);
               if(filename) {
                   var a_link = document.createElement('a');
                   if(typeof a_link.download == 'undefined') {
                       window.location = download_URL;
                   }else {
                       a_link.href = download_URL;
                       a_link.download = filename;
                       document.body.appendChild(a_link);
                       a_link.click();
                   }
               }else {
                   window.location = download_URL;
               }
               setTimeout(function() {
                   URL.revokeObjectURL(download_URL);
               }, 10000);
           }
        }else {
            alert('error')';//do something...
        }
    }; 
    xhr.setRequestHeader('Content-type', 'application/*');
    xhr.send();
}

1

我几分钟前回答了类似的问题:Spring REST + jQuery发送响应中的文件给用户


我建议您使用这个JS插件https://github.com/johnculviner/jquery.fileDownload来下载文件,而不是直接使用$.ajax。您可以在那里找到所有官方文档。
另外,在您的控制器中,您需要获取HttpServletResponse并将byte[]写入outputstream,并在响应中放置一个cookie以通知JS插件(因为它需要它)。
例如:
@RequestMapping(value = "/download", method = RequestMethod.GET)
    public void getFilesInZIP(@RequestParam("filenames[]") String[] filenames, HttpServletResponse httpServletResponse){
        byte[] file = service.packFilesToZIPArchiveAndReturnAsByteArray(filenames);

        Cookie cookie = new Cookie("fileDownload", "true");
        cookie.setPath("/");

        httpServletResponse.addCookie(cookie);
        httpServletResponse.setContentType("application/zip");
        httpServletResponse.setHeader("Content-Disposition", "attachment;filename=files.zip");
        httpServletResponse.getOutputStream().write(file);

    }

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅链接的答案可能会失效。- 来自审查 - Nate Barbettini
这是另一个帖子中的同样问题。我更喜欢给他我的答案链接,而不是复制粘贴。 - Roman
明白了。在StackOverflow上,我们通常尽量避免使用仅包含链接的答案(这里有一些相关讨论)。在评论中使用链接是完全可以的,或者您可以尝试概括答案的关键要点以及链接。 - Nate Barbettini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接