Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 562 Vote(s) - 3.46 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Spring - download response as a file

#1
I am writing application using AngularJS and Spring. I would like to send request to the server and download response returned from controller as a file. In controller I have content of csv file (as string) i.e. `1;2;3;4` (1 row, 4 columns). What is the simplest way to download this response as a file?

Below, I posted my simplified code.
In Spring controller:

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

In javascript (AngularJS)

return $http({method: 'GET', url: 'csv/'});

I was trying to write to the response stream also (below), setting headers, but on client side I always get this content as a string - not as a file to download.

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

Does anyone knows how to write controller's method correctly in order to download response as a file on client side?
Reply

#2
You can't download a file through an XHR request (which is how Angular makes it's requests). See

[To see links please register here]

You either need to go to the URL via `$window.open` or do the iframe trick shown here:

[To see links please register here]

Reply

#3
I've wrestled with this myself, trying to make it work from the server. Couldn't. Instead...

1. To clarify on @dnc253's answer, `$window.open(URL)` is a method for having an Angular application open a given URL in another window. (It's really just a testable angular proxy for the universal `window.open()`.) This is a great solution, preserves your history, and gets the file downloaded and possibly renders it in that fresh browser window if that's supported. But it often runs into popup blockers, which is a huge problem for reliability. Users often simply don't understand what's going on with them. So, if you don't mind immediately downloading the file with the *current* window, you can simply use the equally effective universal javascript method: `location.href = "uriString"`, which works like a charm for me. Angular doesn't even realize anything has happened. I call it in a promise handler for once my POST/PUT operation has completed. If need be, have the POST/PUT return the URL to call, if you can't already infer it. You'll get the same behavior for the user as if it had downloaded in response to the PUT/POST. For example:

$http.post(url, payload).then(function(returnData){
var uriString = parseReturn(returnData);
location.href="uriString"
})

2. You can, in fact, download something directly from an XHR request, but it requires full support for the HTML5 file API and is usually more trouble than it's worth unless you need to perform local transformations upon the file before you make it available to the user. (Sadly, I lack the time to provide details on that but there are other SO posts about using it.)
Reply

#4
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>
Reply

#5
It is possible to download a file using XHR request. You can use angular $http to load the file and then use Blob feature of HTML5 to make browser save it. There is a library that can help you with saving: [FileSaver.js][1].


[1]:

[To see links please register here]

Reply

#6
//JAVA PART

@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>
Reply

#7
> I have written comments below to understand code sample. Some one if using, they can follow it , as I named the files accordingly.

1. IF server is sending blob in the response, then our client should be able to produce it.

2. As my purpose is solved by using these. I can able to download files, as I have used type: 'application/*' for all files.

3. Created "downloadLink" variable is just technique used in response so that, it would fill like some clicked on link, then response comes and then its href would be triggered.




<!-- begin snippet: js hide: false -->

<!-- language: lang-js -->

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;
});
},
};
}])





<!-- end snippet -->
Reply

#8
Just in case you guys need it,
Here a couple of links that can help you:

1.

[To see links please register here]

2.

[To see links please register here]


Cheers
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through