问题
I'm using Spring boot and Angular JS . I have a Spring REST Controller that I use to download a File. when I call it using http://localhost:8080/download it works and the file is downloaded. Now I have a button ,when I click on it , I the file will be downloaded . so I wrote a function in my angular js controller to get the url of my spring web service but when I tested it nothing happened . what should I do to fix this ? Is there a better way to download files using Spring and Angular ?
/**
* Size of a byte buffer to read/write file
*/
private static final int BUFFER_SIZE = 4096;
private String filePath = "C:\\Users\\marwa\\Desktop\\marwa\\gg.jpg";
/**
* Method for handling file download request from client
*/
@RequestMapping (value="/download", method=RequestMethod.GET )
public void doDownload(HttpServletRequest request,
HttpServletResponse response) throws IOException {
// get absolute path of the application
ServletContext context = request.getServletContext();
String appPath = context.getRealPath("");
System.out.println("filepath = " + filePath);
// construct the complete absolute path of the file
File downloadFile = new File(filePath);
FileInputStream inputStream = new FileInputStream(downloadFile);
// get MIME type of the file
String mimeType = context.getMimeType(filePath);
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
// set content attributes for the response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// set headers for the response
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"",
downloadFile.getName());
response.setHeader(headerKey, headerValue);
// get output stream of the response
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
// write bytes read from the input stream into the output stream
while ((bytesRead = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outStream.close();
}
my angular js function ( I added console.log("ok") to see if I get a result from the spring controller and it printed ok )
$scope.downloadFile = function () {
$http({method: 'GET', url: '/download'}).
success(function(result) {
console.log("ok");
}).
error(function(data, status, headers, config) {
console.log("oops");
});
};
and my button
<button class="btn btn-success" ng-click="downloadFile()">download</button>
回答1:
It's working for me :
Spring controller :
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 Service :
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; } }; } ]); })();
AngularJs config :
app.js
(function() { 'use strict'; var myApp = angular.module('myApp', ['components.donwload']); /* myApp.config([function () { }]); myApp.run([function () { }]);*/ })();
AngularJs controller :
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>
回答2:
You are not able to download file because Angular is Expecting a JSON response.
You have to tell Angular that you are going to receive ArrayBuffer
in response.
$http.post('Api/DownloadURL',$scope.data,{responseType:'arraybuffer'})
回答3:
I solved this problem using the following:
$scope.getReport = function() {
var downloadPath = 'your/spring/controller/address';
window.open(downloadPath, '_blank', '');
}
and call getReport()
using ng-click
from your html page.
来源:https://stackoverflow.com/questions/29747136/download-a-file-using-angular-js-and-a-spring-based-restful-web-service