I try to download a file. The action is triggered by ajax()
POST request. The request sends data in JSON format to the controller. The controller generates the file (bytes) and sends it back.
JavaScript:
function getLicenseFile() {
$.ajax({
type: 'POST',
url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: ko.mapping.toJSON(licenseModel),
success: function (data) {
console.log("in sucess")
},
error:function (xhr, ajaxOptions, thrownError){
console.log("in error")
}
});
}
Controller:
@RequestMapping(value = "/licenses/rest/downloadLicenseFile", method = RequestMethod.POST)
@ResponseStatus(value=HttpStatus.OK)
@ResponseBody
public void createLicenseFile(@Valid @RequestBody License license, HttpServletResponse response) throws Exception {
logger.debug("Contoller License in: "+ license);
byte[] licensedata = licenseEncodeDefaultService.createLicenseFile(license);
logger.debug("licenseData: " + new String(licensedata));
response.setHeader("Content-Disposition", "attachment; filename=\"" + license.getCustomer() + ".license\"");
response.getOutputStream().write(licensedata);
response.flushBuffer();
}
OK
)So what do I do wrong or what is the proper way to do this?
Just send a URL of file in response and then "visit" it in your success
callback.
function getLicenseFile() {
$.ajax({
type: 'POST',
url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: ko.mapping.toJSON(licenseModel),
success: function (data) {
window.open(data.fileUrl);
// or window.location.href = data.fileUrl;
},
error:function (xhr, ajaxOptions, thrownError) {
console.log("in error");
}
});
}
data.fileUrl
should be set in response by server to say client where to get the file.
So your server will send a response with JSON like
{
"fileUrl": "http://mysite.com/files/0123456789"
}
@will824 As you ask I'll post my own solution.
I used a workaround in controller and save the file temporarily in the files ystem (/tmp
). I split up the function in 2 steps. Creating and downloading.
This is not very nice but good enough for me.
Controller (creates a file, will be saved on the server file system):
@RequestMapping(value = "/licenses/rest", method = RequestMethod.PUT)
@ResponseStatus(value=HttpStatus.OK)
@ResponseBody
public String createLicenseFile(@Valid @RequestBody License license) throws Exception {
// create encrypted license file and send the name back to view
String fileName = licenseEncodeDefaultService.createLicenseFile(license);
return fileName;
}
Controller (downloads a file):
@RequestMapping(value = "/licenses/downloadFile/{file}", method = RequestMethod.GET)
public void downloadLicenseFile(@PathVariable("file") String file, HttpServletResponse response) throws Exception {
// create full filename and get input stream
File licenseFile = new File ("/tmp/" + file);
InputStream is = new FileInputStream(licenseFile);
// set file as attached data and copy file data to response output stream
response.setHeader("Content-Disposition", "attachment; filename=\"" + file + ".license\"");
FileCopyUtils.copy(is, response.getOutputStream());
// delete file on server file system
licenseFile.delete();
// close stream and return to view
response.flushBuffer();
}
JavaScript:
function getLicenseFile() {
//console.log(ko.mapping.toJSON(licenseModel));
$.ajax({
type : 'PUT',
url : '${pageContext.request.contextPath}/licenses/rest',
dataType : 'text',
contentType : 'application/json;charset=UTF-8',
data : ko.mapping.toJSON(licenseModel),
success : function(data) {
window.location.href = '${pageContext.request.contextPath}/licenses/downloadFile/'
+ data;
},
error : function(xhr, ajaxOptions, thrownError) {
// error handling
}
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With