How can I get download location browser in spring mvc controller? - java

The problem is next necessary to make file on server and after sending to client and print.
#RequestMapping(value = "/some", method = RequestMethod.GET)
public void getFileForPrint(HttpServletResponse response,
#RequestParam(value = "id", required = true) Long id,
#RequestParam(value = "print", defaultValue = "false") Boolean print) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fname);
ServletOutputStream out = response.getOutputStream();
somefile.write(out);
Desktop.getDesktop.print(new File("download location browser"));}
}

If you mean by when you are hitting an end point you want to download a file immediately then the following code should help you.
#RequestMapping(value = "/somePath", method = RequestMethod.GET)
#ResponseBody
public void getFileForPrint(HttpServletResponse response,
#RequestParam(value = "id", required = true) Long id,
#RequestParam(value = "print", defaultValue = "false") Boolean print) throws Exception {
String filename="nameOfFileWhenDownloaded.txt";
try {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());
osw.write(contentsOfTheFile);
osw.flush();
osw.close();
response.flushBuffer();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Error is sending file");
}
}

Related

Why Multipart form "restream" from gateway microservice isn't working and attached file isn't resent?

I have a controller in gateway microservice that accepts the MultipartFile and resends to the service behind it
#PostMapping
public ResponseEntity upload(#ApiParam(name = "file", value = "File", required = true) MultipartFile file)
throws BaseException {
if (Objects.isNull(file)){
throw new CheckFieldException("file", MultipartFile.class);
}
if (megabyte * maxFileSize - file.getSize() < 0){
return ResponseEntity.accepted().body(new DocumentResponseDTO(false, "File size exceeds " + maxFileSize + "MB"));
}
DiscoveryConfig.CashTracking config = discoveryConfig.getCashTracking();
UriComponents uriStatementUpload = UriComponentsBuilder.newInstance().scheme(config.getScheme())
.host(config.getHost()).port(config.getPort()).path(config.getExcelNominalOperationsPath()).build(true);
try {
HttpEntity<byte[]> fileEntity = new HttpEntity(file.getBytes());
ResponseEntity<DocumentResponseDTO> entity = restTemplate.postForEntity(uriStatementUpload.toUri(), fileEntity, DocumentResponseDTO.class);
return entity;
} catch (HttpClientErrorException e) {
return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
} catch (IOException e) {
return ResponseEntity.status(500).body("IOException while getting bytes stream from file");
}
}
and in CashTracking service there is also file upload like that:
#PostMapping(value = "/upload")
public ResponseEntity uploadExcelNominalOperationsFile(#ApiParam(name = "file", value = "File", required = true) MultipartFile file) throws IOException {
try (InputStream is = file.getInputStream()) {
log.info("Processing incoming Excel file with nominal operations");
Workbook workbook = new XSSFWorkbook(is);
log.info("Processing workbook");
Sheet sheet = workbook.getSheetAt(0);
log.info("Processing the first sheet");
List<NominalOperationVO> nominalOperationVOs = new ArrayList<>();
List<String> fileHeaders = new ArrayList<>();
And when the file is actually uploaded to the gateway service, the service behind it starts processing the file upload, but the MultipartFile file is null. I have explicitly put it in the Entity I have sent to the service behind the gateway, the question, what I'm doing wrong if it is null? If I do upload to that microservice directly, it process the request correctly.
The main stuff I was missing was putting the Http headers per specific multipart form's parts. They should be identical to what has been sent to the gateway service.
public ResponseEntity upload(#ApiParam(name = "file", value = "Файл", required = true) MultipartFile file)
throws BaseException {
if (Objects.isNull(file)){
throw new CheckFieldException("file", MultipartFile.class);
}
if (megabyte * maxFileSize - file.getSize() < 0){
return ResponseEntity.accepted().body(new DocumentResponseDTO(false, "File size exceeds " + maxFileSize + "MB"));
}
DiscoveryConfig.CashTracking config = discoveryConfig.getCashTracking();
UriComponents uriStatementUpload = UriComponentsBuilder.newInstance().scheme(config.getScheme())
.host(config.getHost()).port(config.getPort()).path(config.getExcelNominalOperationsPath()).build(true);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultipartBodyBuilder multipartBodyBuilder = new MultipartBodyBuilder();
//here is the really needed stuff with 2 headers
Resource resource = new ByteArrayResource(file.getBytes());
multipartBodyBuilder.part("file", resource)
.header("Content-Type",file.getContentType())
.header("Content-Disposition","form-data; name=\"file\"; filename=\""+file.getOriginalFilename()+"\"");
// multipart/form-data request body
MultiValueMap<String, HttpEntity<?>> body = multipartBodyBuilder.build();
HttpEntity<MultiValueMap<String, HttpEntity<?>>> requestEntity
= new HttpEntity<>(body, headers);
ResponseEntity<DocumentResponseDTO> entity = restTemplate.postForEntity(uriStatementUpload.toUri(), requestEntity, DocumentResponseDTO.class);
return entity;
} catch (HttpClientErrorException e) {
return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
} catch (IOException e) {
return ResponseEntity.status(500).body("IOException while getting bytes stream from file");
}
}

Files not getting Downloaded in Spring

There is a page where i have files list. On cliking on any of the .txt it must get downloaded and a notification should be displayed as the notification we get in download anything on GoogleChrome.
This is my Js which is called after cliking on .txt files
Here i am doing is, i am getting the filename and the filepath of the selected file. And then using ajax sending those filename and filepath to the spring servlet.
if (options.downloadable) {
$(easyTree).find('.easy-tree-toolbar').append('<div class="fileDownload"><button class="btn btn-default btn-sm btn-primary"><span class="glyphicon glyphicon-circle-arrow-down"></span></button></div>');
$(easyTree).find('.easy-tree-toolbar .fileDownload > button').attr('title', options.i18n.downloadTip).click(function() {
var selected = getSelectedItems();
var fileName = $(selected).find(' > span > a').text();
alert("fileName**" + fileName);
var hrefValue = $(selected).find(' > span > a').attr('href');
alert("hrefValue**" + hrefValue);
if (selected.length <= 0) {
$(easyTree).prepend(warningAlert);
$(easyTree).find('.alert .alert-content').html(options.i18n.downloadNull);
} else {
$.ajax({
url: "/ComplianceApplication/downloadFileFromDirectory",
type: "GET",
data: {
hrefValue: hrefValue,
fileName: fileName
},
success: function(data) {
//$(selected).remove();
//window.location.reload();
},
error: function(e) {
}
});
}
});
}
This is my springController. Here I am getting all the data properly but the problem is file is not getting downloaded and am not even getting any error so that I can come to know what mistake I am doing.
#RequestMapping(value="/downloadFileFromDirectory",method = RequestMethod.GET)
public #ResponseBody void downloadFileFromDirectory(#PathVariable("fileName") String fileName,#RequestParam(value = "hrefValue") String hrefValue,HttpServletRequest request, HttpServletResponse response,Model model){
System.out.println("hrefValue***"+hrefValue);
String filePath = hrefValue;
ServletContext context = request.getSession().getServletContext();
File downloadFile = new File(filePath);
FileInputStream inputStream = null;
OutputStream outStream = null;
try {
inputStream = new FileInputStream(downloadFile);
response.setContentLength((int) downloadFile.length());
response.setContentType(context.getMimeType(downloadFile.getName()));
// response header
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
//String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
response.setHeader(headerKey, headerValue);
// Write response
outStream = response.getOutputStream();
IOUtils.copy(inputStream, outStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != inputStream)
inputStream.close();
if (null != outStream)
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Any suggestions ???
I usually use this kind of code with no problem:
public ResponseEntity<InputStreamResource> downloadFile(#PathVariable("idForm") String idForm)
{
try
{
File parent = new File(csvFilesPath);
File file = new File(parent, idForm+".csv");
HttpHeaders respHeaders = new HttpHeaders();
MediaType mediaType = new MediaType("text","csv");
respHeaders.setContentType(mediaType);
respHeaders.setContentLength(file.length());
respHeaders.setContentDispositionFormData("attachment", "file.csv");
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}
catch (Exception e)
{
String message = "Errore nel download del file "+idForm+".csv; "+e.getMessage();
logger.error(message, e);
return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
The problem it's in you ajax code, so you can use JQuery File Download.
It's as simple as
$.fileDownload('/url/to/download.pdf');
Here you can see a tutorial
http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/

How to set HttpEntity in restTemplate-execute

Is there a way to set the httpEntiy in the restTemplate.execute Method? I have to put the Authorization in the header, so thats why I can not exclude it. As a ResponseEntity I get a InputStreamResource.
This is working without HttpEntiy set:
File responseFile = restTemplate.execute(
uriComponents.toUri(),
HttpMethod.GET, null,
new ResponseExtractor<File>() {
#Override
public File extractData(ClientHttpResponse response) throws IOException {
File serverFile = fileProcessHelper.createFile(pathToFile);
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(serverFile));
byte[] bytes = IOUtils.toByteArray(response.getBody());
stream.write(bytes);
stream.close();
return serverFile;
}
});
This is NOT working. Error is: java.io.IOException: stream is closed
ResponseEntity<InputStreamResource> responseEntity = restTemplate.exchange(
uriComponents.toUri(),
HttpMethod.GET, requestEntity,
InputStreamResource.class);
InputStreamResource stream = new InputStreamResource(responseEntity.getBody().getInputStream());
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentLength(stream.contentLength());
response.setHeader("Content-Disposition", "attachment; filename=" + stream.getFilename());
return ResponseEntity.ok().headers(respHeaders).body(stream);
Or is there a way to reopen the inputstreamresource?
Thanks in advance!
Ok. I found a solution:
in the RquestCallback you can set the headers:
RequestCallback requestCallback = new RequestCallback() {
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
request.getHeaders().set("Authorization", "Basic " + base64Creds);
}
};

How to upload file to a spring mvc RestController using post method

I'm having the follwing controller:
#RequestMapping(value = "/uploadCert", method = RequestMethod.POST)
#ResponseBody
public String uploadCert( #RequestParam(value = "file", required = false) List<MultipartFile> files){
for (MultipartFile file : files) {
String path = "tempFolder";
File targetFile = new File(path);
try {
FileUtils.copyInputStreamToFile(file.getInputStream(), targetFile);
} catch (IOException e) {
e.printStackTrace();
}
}
return "done";
}
Tested by the following unit test:
#Test
public void uploadCertFile() throws Exception {
//given
MockMultipartFile file = new MockMultipartFile("file", "test.txt", "text/plain", "bar".getBytes());
MockHttpServletRequestBuilder request = MockMvcRequestBuilders.fileUpload("/uploadCert").file(file);
System.out.println(request);
//when
ResultActions resultActions = mockMvc.perform(request);
//then
MvcResult mvcResult = resultActions.andReturn();
assertEquals(200, mvcResult.getResponse().getStatus());
File savedFile = new File("./test.txt");
assertTrue(savedFile.exists());
savedFile.delete();
}
which it workign good, i have another server in java code that would need to upload files into the above controller. I was trying to look for parallel of MockMVCRequestMapping to be use in the code but could not find it, what should i use insted to send this web request from a java code?
You can do something like this:
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity<String> uploadDocument(MultipartHttpServletRequest request, HttpServletResponse response) throws IOException {
Iterator<String> iterator = request.getFileNames();
MultipartFile multipartFile = null;
while (iterator.hasNext()) {
multipartFile = request.getFile(iterator.next());
final String fileName = multipartFile.getOriginalFilename();
final String fileSize = String.valueOf(multipartFile.getSize());
//do rest here
}
}

retrieve image from database using spring mvc

UserEntityManager.java
#RequestMapping(value = "getImages.do", method = RequestMethod.GET)
public byte[] getImage(final String username) {
Blob img = null;
byte[] imgData = null;
sql = "SELECT UserPhoto FROM u_logininfo WHERE LoginName = ?";
try {
img = jdbcTemplate.queryForObject(sql, new Object[]{username}, new RowMapper<Blob>() {
#Override
public Blob mapRow(ResultSet rs, int arg1)
throws SQLException {
Blob blob = rs.getBlob("UserPhoto");
return blob;
}
});
imgData = img.getBytes(1, (int) img.length());
return imgData;
//File file = new File
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
And this is my controller
UserController.java
#RequestMapping(value = "getImages.do" , method = RequestMethod.GET)
private ModelAndView viewImages(Model model){
String userName = (String)SecurityContextHolder.getContext().getAuthentication().getName();
byte[] image = userEntityManager.getImage(userName);
model.addAttribute("images", image);
return new ModelAndView("Fun Zone/Photo");
}
and jsp
<div class="col-sm-2" style="margin-top: 288px; margin-left: 291px;">
<img src="getImages.do">
</div>
I want to display the image on the .jsp page using Spring MVC 3 But image not display in jsp.
I'd suggest you to rewrite the controller. There seems so many things that are not exactly the way it's supposed to be. Do something like this:
#RequestMapping(value = "getImages.do", method = RequestMethod.GET)
public void viewImages(HttpServletRequest request, HttpServletResponse response) throws IOException {
// get the image
String userName = (String)SecurityContextHolder.getContext().getAuthentication().getName();
byte[] image = userEntityManager.getImage(userName);
// get MIME type of the file
String mimeType = "application/octet-stream";
// set content attributes for the response
response.setContentType(mimeType);
response.setContentLength((int) image.length());
// set headers for the response
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=image.jpeg");
response.setHeader(headerKey, headerValue);
// get output stream of the response
OutputStream outStream = response.getOutputStream();
// get input stream and a fixed size buffer
InputStream is = new ByteArrayInputStream(image);
byte[] buffer = new byte[4096];
// write data into output stream
int read = -1;
while(read = in.read(buffer)) != -1) {
outStream.write(buffer, 0, read);
}
// close output stream
outStream.flush();
outStream.close();
}
And also get rid of that RequestMapping on UserEntityManager.

Categories

Resources