Spring - download response as a file
我正在使用AngularJS和Spring编写应用程序。 我想向服务器发送请求并下载从控制器返回的响应作为文件。 在控制器中,我有csv文件的内容(作为字符串),即
下面,我发布了我的简化代码。
在Spring控制器中:
1 2 3 4 5 | @RequestMapping(value ="/csv", method = GET) @ResponseBody public String getCsvFile() { return getCsvContent(); } |
在javascript(AngularJS)
1 | return $http({method: 'GET', url: 'csv/'}); |
我也试图写入响应流(下面),设置标题,但在客户端我总是把这个内容作为字符串 - 而不是作为要下载的文件。
1 2 3 4 5 6 7 8 9 10 11 | @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提出请求的方式)。请参阅为什么使用ajax请求无法下载文件?您需要通过
我自己也在努力解决这个问题,试图让它从服务器上运行。不能。代替...
为了澄清@ dnc253的答案,
1 2 3 4 | $http.post(url, payload).then(function(returnData){ var uriString = parseReturn(returnData); location.href="uriString" }) |
实际上,您可以直接从XHR请求下载内容,但它需要完全支持HTML5文件API,并且通常比它的价值更麻烦,除非您需要在文件上对用户可用之前对文件执行本地转换。 (遗憾的是,我没有时间提供详细信息,但还有其他SO帖子关于使用它。)
可以使用XHR请求下载文件。您可以使用angular $ http加载文件,然后使用HTML5的Blob功能使浏览器保存它。有一个库可以帮助您保存:FileSaver.js。
万一你需要它,
这里有几个可以帮助您的链接:
干杯
I have written comments below to understand code sample. Some one if using, they can follow it , as I named the files accordingly.
IF服务器在响应中发送blob,然后我们的客户端应该能够生成它。
因为我的目的通过使用这些来解决。我可以下载文件,因为我使用了类型:'application / *'表示所有文件。
创建"downloadLink"变量只是用于响应的技术,因此,它会像点击链接一样填充,然后响应来,然后它的href将被触发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | controller.js //this function is in controller, which will be trigered on download button hit. $scope.downloadSampleFile = function() { //create sample hidden link in document, to accept Blob returned in the response from back end var downloadLink = document.createElement("a"); document.body.appendChild(downloadLink); downloadLink.style ="display: none"; //This service is written Below how does it work, by aceepting necessary params downloadFile.downloadfile(data).then(function (result) { var fName = result.filename; var file = new Blob([result.data], {type: 'application/*'}); var fileURL = (window.URL || window.webkitURL).createObjectURL(file); //Blob, client side object created to with holding browser specific download popup, on the URL created with the help of window obj. downloadLink.href = fileURL; downloadLink.download = fName; downloadLink.click(); }); }; services.js .factory('downloadFile', ["$http", function ($http) { return { downloadfile : function () { return $http.get(//here server endpoint to which you want to hit the request , { responseType: 'arraybuffer', params: { //Required params }, }).then(function (response, status, headers, config) { return response; }); }, }; }]) |
// JAVA PART
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | @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> Test <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> |
它对我有用:
-
Spring控制器:
DownloadController.java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55package 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 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27(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;
}
};
}
]);
})(); -
AngularJs config:
app.js 1
2
3
4
5
6
7
8
9
10
11
12
13(function() {
'use strict';
var myApp = angular.module('myApp', ['components.donwload']);
/* myApp.config([function () {
}]);
myApp.run([function () {
}]);*/
})(); -
AngularJs控制器:
download.controller.js 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15(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 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<!DOCTYPE html>
<html ng-app="myApp">
<head>
My App
<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>
<button ng-click="ctrl.download('fileName.txt')">Download</button>
<script src="bower_components/angular/angular.min.js">
<!-- App config -->
<script src="scripts/app/app.js">
<!-- Download Feature -->
<script src="scripts/app/download/download.controller.js">
<!-- Components -->
<script src="scripts/components/download/download.service.js">
</body>
</html>