Currently, this is my code in the controller to return a XLS file for download:
#RequestMapping(value = "/export-data/", method = RequestMethod.GET)
public ResponseEntity exportAllData() {
ResponseEntity respEntity = null;
SheetDownload sheetDownload = new SheetDownload();
try {
ByteArrayOutputStream result = sheetDownload.createMentoringSheet();
HttpHeaders responseHeaders = new HttpHeaders();
byte[] out = result.toByteArray();
responseHeaders.add("content-disposition", "attachment; filename=export-data.xlsx");
responseHeaders.add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
respEntity = new ResponseEntity(out, responseHeaders,HttpStatus.OK);
}catch(Exception e){
respEntity = new ResponseEntity ("File Not Found", HttpStatus.OK);
}
return respEntity;
}
When I go to the "network" in Chrome, all I see in the response is:
So, there's no trigger to browser download, for example. The goal is to return the file to be downloaded in the proper format (XLSX).
Can someone help me?
Thank you in advance.
Related
I'm using SpringBoot 3.0.1 and I'm trying to get a file stored in the backend using Axios.
The controller is the following:
#GetMapping(value = "/api/files/{fileName}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<?> getFile(final #PathVariable("fileName") String fileName) {
try {
Path filePath = Path.of(fileName);
File file = filePath.toFile();
HttpHeaders responseHeaders = new HttpHeaders();
String filename = filePath.getFileName().toString();
responseHeaders
.setContentDisposition(ContentDisposition.builder("attachment")
.filename(filename, StandardCharsets.UTF_8)
.build());
FileSystemResource fileSystemResource = new FileSystemResource(file);
return ResponseEntity
.ok()
.headers(responseHeaders)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(file.length())
.lastModified(file.lastModified())
.body(fileSystemResource);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
When I get the answer (status is 200), the header I've set in the controller is not given. In particular, the Content-Disposition header is not defined in the answer.
I'm wondering if there is any missing configuration that must be set in Sprint Boot in order to be allowed to set a custom header. Anyone who knows what can cause this and how to fix it?
I have a controller and an Exporter class to create pdf of one class data in Spring boot. It works at localhost. And I can send emails with attachments which are in the resources/static/ directory from this link:
https://asbnotebook.com/2020/01/26/send-email-with-attachment-spring-boot/
I want to email the pdf file created at fly. I tried to combine them but it didnt work.
public String sendMail(EmailRequestDto request, Map<String, String> model) {
String response;
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
Template template = configuration.getTemplate("email.ftl");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
helper.setTo(request.getTo());
helper.setFrom(request.getFrom());
helper.setSubject(request.getSubject());
helper.setText(html, true);
List<PurchaseDetail> cities = (List<PurchaseDetail>)basketService.getPurchases();
ByteArrayInputStream bis = InvoicePdfExporter.citiesReport(cities);
HttpHeaders headers = new HttpHeaders(); headers.add("ContentDisposition",
"inline; filename=citiesreport.pdf");
InputStreamResource rs= (new InputStreamResource(bis)) ;
//this gives error because rs is a inputStreamResource but not InputStream
helper.addAttachment("citiesreport.pdf",newByteArrayResource(IOUtils.toByteArray(rs)));
mailSender.send(message);
response = "Email has been sent to :" + request.getTo();
} catch (MessagingException | IOException | TemplateException e) {
response = "Email send failure to :" + request.getTo();
}
return response;
}
And my working controller class which creates pdf. InvoicePdfExporter class adds datatable to document and returns as return new ByteArrayInputStream(out.toByteArray());:
#RequestMapping(value = "/pdfreport", method = RequestMethod.GET,
produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> citiesReport() throws IOException
{
List<PurchaseDetail> purchases = (List<PurchaseDetail>)
basketService.getPurchases();
ByteArrayInputStream bis = InvoicePdfExporter.citiesReport(purchases);
HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition",
"inline; filename=citiesreport.pdf");
return
ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF)
.body(new InputStreamResource(bis)) ; }
}
I really need help I really dont understand from IOStreams, I tried many things but none of them solved my problem. Thanks!!
Edit:
I solved this problem by changing the return type of my InvoicePdfExporter to InputStreamSource and changed to this:
List<PurchaseDetail> cities = (List<PurchaseDetail>)basketService.getPurchases();
InputStreamSource bis =InvoicePdfExporter.citiesReport(cities);
HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition",
"inline; filename=citiesreport.pdf");
helper.addAttachment("citiesreport.pdf",bis, "application/pdf" );
I'm using this code to download a image from angular app.
#RequestMapping("/files/{merchant_id}")
public ResponseEntity<byte[]> downloadLogo(#PathVariable("merchant_id") Integer merchant_id) throws IOException {
File file = new File(UPLOADED_FOLDER, merchant_id.toString() + "/merchant_logo.png");
InputStream in = FileUtils.openInputStream(file);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
}
But when I try to download a image which is not found I get NPE which is normal. How I can return empty response when the image file is not found? Something like:
return ResponseEntity.ok(...).orElse(file.builder().build()));
Can you give me some advice how to fix this?
Just choose a ResponseEntity constructor that is without body argument to create ResponseEntity
File file = new File(UPLOADED_FOLDER, merchant_id.toString() + "/merchant_logo.png");
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
if (!file.exists()) {
return new ResponseEntity<byte[]>(headers,HttpStatus.NOT_FOUND);
}else{
InputStream in = FileUtils.openInputStream(file);
return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.OK);
}
I change it to return 404 status code when the images does not exist and 200 when the images exist which better align with HTTP status code 's semantic meaning.
I'm creating spring boot application that send a file in body response, to this i use this code :
FileSystemResource pdfFile = new FileSystemResource(outputFile);
return ResponseEntity
.ok()
.contentLength(pdfFile.contentLength())
.contentType(MediaType.parseMediaType("application/pdf"))
.body(new ByteArrayResource(IOUtils.toByteArray(pdfFile.getInputStream())));
I'm wondering if there's any alternative way for send file other than using FileSystemResource ?
Please, If there's any suggestion, do not hesitate.
Thank You !
This is a simplified version of how I usually do it, but it does pretty much the same thing:
#RequestMapping(method = RequestMethod.GET, value = "/{id}")
public ResponseEntity<byte[]> getPdf(#PathVariable Long id) throws IOException {
final String filePath = pdfFilePathFinder.find(id);
final byte[] pdfBytes = Files.readAllBytes(Paths.get(filePath));
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
headers.setContentDispositionFormData("attachment", null);
headers.setCacheControl("no-cache");
return new ResponseEntity<>(pdfBytes, headers, HttpStatus.OK);
}
I have write a simple Spring + Angular application just for learn more about it.
I have a spring controller which is mapped to a URL and when an request comes it returns an image.
I have written all the codes and the spring controller returns me the image but when i set it in the HTML it is not displayed correctly
here is my spring controller
#RequestMapping(value = "image/", method = RequestMethod.GET)
public ResponseEntity<byte[]> getChequeImage(HttpSessionsession,#PathVariable("itemId") Integer itemId,
HttpServletResponse response) {
try{
InputStream in = new FileInputStream(new File("path_to_image.jpg"));
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.OK);
}catch (IOException e){
LOGGER.error(e);
e.getMessage(), response);
return null;
}
}
here is my HTML code
<img src="{{image}}"/>
image is an Angular variable. Angular service is sending the request and binding the data to the image variable
here is the angular code
#scope.image = "data:image/jpg," + data_from_the_api;
You can't use raw image bytes directly on the page, but you can do Base64 encoding, this would be the adaptations
#RequestMapping(value = "image/", method = RequestMethod.GET)
public ResponseEntity<String> getChequeImage(HttpSessionsession,#PathVariable("itemId") Integer itemId,
HttpServletResponse response) {
try{
InputStream in = new FileInputStream(new File("path_to_image.jpg"));
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
byte[] binaryData = IOUtils.toByteArray(in)
byte[] encodeBase64 = Base64.encodeBase64(binaryData);
String base64Encoded = new String(encodeBase64, "UTF-8");
return new ResponseEntity<String>(base64Encoded , headers, HttpStatus.OK);
}catch (IOException e){
LOGGER.error(e);
e.getMessage(), response);
return null;
}
}
and as TechMa9iac said in the comment you should set #scope.image = "data:image/jpg;base64," + data_from_the_api;