Spring-将响应下载为文件
我正在使用AngularJS和Spring编写应用程序。我想向服务器发送请求,并下载控制器返回的作为文件的响应。在控制器中,我有csv文件的内容(作为字符串),即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
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的方法。(它实际上只是universalwindow.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',
参数:{
//必需的