【问题标题】:Spring Rest and jQuery Ajax File DownloadSpring Rest 和 jQuery Ajax 文件下载
【发布时间】:2016-01-04 21:18:24
【问题描述】:

我目前正在使用 jQuery 和 Spring Rest。 jQuery 用于上传和下载文件到服务器。上传过程运行良好,但下载文件没有什么问题。所以场景是,在视图中,用户将选择n个要下载的文件并单击下载按钮。一旦用户单击该按钮,文件将被下载。我不想为每个文件下载打开一个新的新标签。我想在同一个窗口下载而不刷新当前视图。我查看了this,但对我帮助不大。有什么办法,我可以做到这一点?

【问题讨论】:

    标签: javascript jquery ajax spring spring-mvc


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      几分钟前我回答了类似的问题:sending file from response to user, Spring REST + jQuery


      我建议你使用这个 JS 插件https://github.com/johnculviner/jquery.fileDownload 来下载文件,而不是直接使用 $.ajax。你可以在那里找到所有的官方文档。

      此外,在您的控制器中,您必须获取 HttpServletResponse 并将 byte[] 写入输出流,并且您必须在响应中放置一个 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);
      
          }
      

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
      • 这是另一个线程中的另一个问题。我更愿意给他我答案的链接,而不是复制+粘贴
      • 明白。不过,我们通常会尝试在 StackOverflow 上避免仅链接的答案。 (这里有一些relevant discussion。)评论中的链接非常好,或者您可以尝试将答案的关键点与链接一起提炼出来。
      猜你喜欢
      • 1970-01-01
      • 2018-02-21
      • 2019-09-28
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 2022-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多