Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring-将响应下载为文件_Spring_Angularjs - Fatal编程技术网

Spring-将响应下载为文件

Spring-将响应下载为文件,spring,angularjs,Spring,Angularjs,我正在使用AngularJS和Spring编写应用程序。我想向服务器发送请求,并下载控制器返回的作为文件的响应。在控制器中,我有csv文件的内容(作为字符串),即1;2.3.4(1行4列)。将此响应下载为文件的最简单方法是什么 下面,我发布了我的简化代码。 在Spring控制器中: @RequestMapping(value = "/csv", method = GET) @ResponseBody public String getCsvFile() { return getCsvCo

我正在使用AngularJS和Spring编写应用程序。我想向服务器发送请求,并下载控制器返回的作为文件的响应。在控制器中,我有csv文件的内容(作为字符串),即
1;2.3.4
(1行4列)。将此响应下载为文件的最简单方法是什么

下面,我发布了我的简化代码。 在Spring控制器中:

@RequestMapping(value = "/csv", method = GET)
@ResponseBody
public String getCsvFile() {
    return getCsvContent();
}
在javascript中(AngularJS)

我也尝试写入响应流(如下),设置标题,但在客户端,我总是以字符串的形式获取这些内容,而不是下载文件

@RequestMapping(value = "/csv", method = GET)
@ResponseBody
public void getCsvFile(HttpServletResponse response) {
    response.setContentType("application/csv");
    response.setHeader("Content-Disposition", "attachment; filename=file.csv");
    response.setContentLength(getCsvContent().getBytes().length);
    ServletOutputStream out = response.getOutputStream();
    out.write(getCsvContent());
    out.flush();
    out.close();
}

有人知道如何正确编写控制器的方法,以便将响应作为文件下载到客户端吗?

您不能通过XHR请求下载文件(这是Angular发出请求的方式)。请看,您需要通过
$窗口转到URL。打开
,或者执行此处显示的iframe技巧:

我自己也在努力解决这个问题,试图从服务器上实现它。不能。相反

  • 为了澄清@dnc253的答案,
    $window.open(URL)
    是一种让角度应用程序在另一个窗口中打开给定URL的方法。(它实际上只是universal
    window.open()
    的一个可测试角度代理)这是一个很好的解决方案,可以保存您的历史记录,下载文件,如果支持的话,还可以在新的浏览器窗口中呈现文件。但它经常遇到弹出窗口拦截器,这对可靠性来说是一个巨大的问题。用户通常根本不了解他们在做什么。因此,如果您不介意立即使用当前窗口下载该文件,您可以简单地使用同样有效的通用javascript方法:
    location.href=“uriString”
    ,这对我来说非常有用。安格尔甚至不知道发生了什么事。一旦我的POST/PUT操作完成,我就在承诺处理程序中调用它。如果需要,让POST/PUT返回要调用的URL(如果您还不能推断)。您将获得与用户下载响应PUT/POST时相同的行为。例如:

    $http.post(url, payload).then(function(returnData){
        var uriString = parseReturn(returnData);
        location.href="uriString"
    })
    
  • 事实上,您可以直接从XHR请求下载某些内容,但它需要对HTML5文件API的完全支持,并且通常比它的价值更麻烦,除非您需要在将文件提供给用户之前对其执行本地转换。(遗憾的是,我没有时间提供这方面的细节,但还有其他关于使用它的帖子。)


  • 万一你们需要的话, 这里有几个链接可以帮助您:

  • 干杯

    这对我有用:

    • Spring控制器:
      DownloadController.java

      package com.mycompany.myapp.controller;
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.OutputStream;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import org.apache.commons.io.IOUtils;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.http.HttpStatus;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.ExceptionHandler;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestMethod;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      
      import com.mycompany.myapp.exception.TechnicalException;
      
      
      @RestController
      public class DownloadController {
      
          private final Logger log = LoggerFactory.getLogger(DownloadController.class);
      
          @RequestMapping(value = "/download", method = RequestMethod.GET)
          public void download(@RequestParam ("name") String name, final HttpServletRequest request, final HttpServletResponse response) throws TechnicalException {
              log.trace("name : {}", name);
      
              File file = new File ("src/main/resources/" + name);
              log.trace("Write response...");
              try (InputStream fileInputStream = new FileInputStream(file);
                      OutputStream output = response.getOutputStream();) {
      
                  response.reset();
      
                  response.setContentType("application/octet-stream");
                  response.setContentLength((int) (file.length()));
      
                  response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
      
                  IOUtils.copyLarge(fileInputStream, output);
                  output.flush();
              } catch (IOException e) {
                  log.error(e.getMessage(), e);
              }
      
          }
      
      }
      
    • AngularJs服务:
      download.Service.js

      (function() {
          'use strict';
      
          var downloadModule = angular.module('components.donwload', []);
      
          downloadModule.factory('downloadService', ['$q', '$timeout', '$window',
              function($q, $timeout, $window) {
                  return {
                      download: function(name) {
      
                          var defer = $q.defer();
      
                          $timeout(function() {
                                  $window.location = 'download?name=' + name;
      
                              }, 1000)
                              .then(function() {
                                  defer.resolve('success');
                              }, function() {
                                  defer.reject('error');
                              });
                          return defer.promise;
                      }
                  };
              }
          ]);
      })();
      
      (function() {
          'use strict';
      
          var myApp = angular.module('myApp', ['components.donwload']);
         /* myApp.config([function () {
      
          }]);
          myApp.run([function () {
      
          }]);*/
      
      
      })();
      
    • AngularJs配置:
      app.js

      (function() {
          'use strict';
      
          var downloadModule = angular.module('components.donwload', []);
      
          downloadModule.factory('downloadService', ['$q', '$timeout', '$window',
              function($q, $timeout, $window) {
                  return {
                      download: function(name) {
      
                          var defer = $q.defer();
      
                          $timeout(function() {
                                  $window.location = 'download?name=' + name;
      
                              }, 1000)
                              .then(function() {
                                  defer.resolve('success');
                              }, function() {
                                  defer.reject('error');
                              });
                          return defer.promise;
                      }
                  };
              }
          ]);
      })();
      
      (function() {
          'use strict';
      
          var myApp = angular.module('myApp', ['components.donwload']);
         /* myApp.config([function () {
      
          }]);
          myApp.run([function () {
      
          }]);*/
      
      
      })();
      
    • AngularJs控制器:
      download.controller.js

      (function() {
          'use strict';
      
          angular.module('myApp')
              .controller('DownloadSampleCtrl', ['downloadService', function(downloadService) {
                  this.download = function(fileName) {
                      downloadService.download(fileName)
                          .then(function(success) {
                              console.log('success : ' + success);
                          }, function(error) {
                              console.log('error : ' + error);
                          });
                  };
              }]);
      })();
      
    • index.html

      <!DOCTYPE html>
      <html ng-app="myApp">
      
      <head>
          <title>My App</title>
          <link rel="stylesheet" href="bower_components/normalize.css/normalize.css" />
          <link rel="stylesheet" href="assets/styles/main.css" />
          <link rel="icon" href="favicon.ico">
      </head>
      
      <body>
          <div ng-controller="DownloadSampleCtrl as ctrl">
              <button ng-click="ctrl.download('fileName.txt')">Download</button>
          </div>
      
          <script src="bower_components/angular/angular.min.js"></script>
      
          <!-- App config -->
          <script src="scripts/app/app.js"></script>
          <!-- Download Feature -->
          <script src="scripts/app/download/download.controller.js"></script>
          <!-- Components -->
          <script src="scripts/components/download/download.service.js"></script>
      </body>
      
      </html>
      
      
      我的应用程序
      下载
      

    可以使用XHR请求下载文件。您可以使用angular$http加载文件,然后使用HTML5的Blob功能让浏览器保存它。有一个库可以帮助您保存:。

    /JAVA部分

    @RequestMapping(value = "/report-excel", method = RequestMethod.GET)
        public ResponseEntity<byte[]> getReportExcel(@RequestParam("bookingStatusType") String bookingStatusType,
                @RequestParam("endDate") String endDate, @RequestParam("product") String product, @RequestParam("startDate") String startDate)throws IOException, ParseException {
    
    //Generate Excel from DTO using any logic after that do the following
    byte[] body = wb.getBytes();
    HttpHeaders header = new HttpHeaders();
            header.setContentType(new MediaType("application", "xlsx"));
            header.set("Content-Disposition", "inline; filename=" + fileName);
            header.setCacheControl("must-revalidate, post-check=0, pre-check=0");
            header.setContentLength(body.length);
    
     return new ResponseEntity<byte[]>(body, header, HttpStatus.OK);
    }
    
    
    
    //HTML PART
    <html>
    <head>
    <title>Test</title>
    <meta http-equiv="content-type" content="application/x-www-form-urlencoded; charset=UTF-8">
    </head>
    <body>
      <form name="downloadXLS" method="get" action="http://localhost:8080/rest/report-excel" enctype="multipart/form-data">
        <input type="text" name="bookingStatusType" value="SALES"></input>
        <input type="text" name="endDate" value="abcd"></input>
        <input type="text" name="product" value="FLIGHT"></input>
        <input type="text" name="startDate" value="abcd"></input>
        <input onclick="document.downloadXLS.submit()" value="Submit"></input>
      </form>
    </body>
    </html>
    
    @RequestMapping(value=“/report excel”,method=RequestMethod.GET)
    public ResponseEntity getReportExcel(@RequestParam(“bookingStatusType”)字符串bookingStatusType,
    @RequestParam(“endDate”)字符串endDate、@RequestParam(“product”)字符串product、@RequestParam(“startDate”)字符串startDate)引发IOException、ParseException{
    //使用任何逻辑从DTO生成Excel,然后执行以下操作
    byte[]body=wb.getBytes();
    HttpHeaders header=新的HttpHeaders();
    setContentType(新媒体类型(“应用程序”、“xlsx”));
    header.set(“内容处置”、“内联;文件名=“+filename”);
    header.setCacheControl(“必须重新验证,后检查=0,预检查=0”);
    header.setContentLength(body.length);
    返回新的响应属性(主体、标题、HttpStatus.OK);
    }
    //HTML部分
    试验
    
    为了理解代码示例,我在下面写了一些评论。如果有人使用,他们可以遵循它,因为我相应地命名了这些文件

  • 若服务器在响应中发送blob,那个么我们的客户机应该能够生成它

  • 因为我的目的是通过使用这些解决的。我可以下载文件,因为我对所有文件都使用了“application/*”类型

  • 创建的“downloadLink”变量只是响应中使用的技术,所以,它会像点击链接一样填充,然后响应出现,然后它的href将被触发

  • controller.js
    //此功能在控制器中,点击下载按钮时触发。
    $scope.downloadSampleFile=function(){
    //在文档中创建示例隐藏链接,以接受后端响应中返回的Blob
    var downloadLink=document.createElement(“a”);
    document.body.appendChild(下载链接);
    downloadLink.style=“显示:无”;
    //下面通过接受必要的参数来描述该服务的工作原理
    downloadFile.downloadFile(数据).then(函数(结果){
    var fName=result.filename;
    var file=newblob([result.data],{type:'application/*'});
    var fileURL=(window.URL | | window.webkitURL).createObjectURL(文件);
    //Blob,客户端对象,通过在window obj帮助下创建的URL上保存特定于浏览器的下载弹出窗口创建。
    downloadLink.href=fileURL;
    downloadLink.download=fName;
    downloadLink.click();
    });
    };
    services.js
    .factory('downloadFile',[“$http”,函数($http){
    返回{
    下载文件:函数(){
    返回$http.get(//此处为您要点击请求的服务器端点
    , {
    响应类型:'arraybuffer',
    参数:{
    //必需的