Create a file download link using Spring Boot and Thymeleaf - java

I have a download link on my page but it doesn't work and get error.
Here's my code.
request mapping :
#RequestMapping(value="/{id}/download", method=RequestMethod.GET)
public ResponseEntity<Resource> downloadFile(#PathVariable Integer id) {
// Load file from database
MsFile file = null;
MsAnnouncement ano = null;
try {
ano = anRepo.findById(id).get();
file = fileService.getFile(ano.getFileId().getId());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(file.getFileType()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getAttachedFileName() + "\"")
.body(new ByteArrayResource(file.getAttachedFile()));
}
html :
<a class=" mx-1 btn btn-secondary" th:href="#{/admin/announcement/{id}/download/(id=${announcement.id})}"
>Download</a>
I just need the file downloaded once when i click the button. But when i try with this code the file cannot be downloaded and get error at the return ResponseEntity.ok():
error following :
AnnouncementController.downloadFile(AnnouncementController.java:130) ~[classes/:na]
At java:130 :
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(file.getFileType()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getAttachedFileName() + "\"")
.body(new ByteArrayResource(file.getAttachedFile()));
}

Related

get content file in java

I used this method to download and get content type
#GetMapping("/downloadFile/")
public ResponseEntity<Resource> downloadFile(#RequestParam String fileName, HttpServletRequest request) {
// Load file as Resource
Resource resource = fileStorageService.loadOneFileAsResource(fileName);
// Try to determine file's content type
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
logger.info("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if(contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
But always detect my content "application/octet-stream", what is problem and what should I do?
thanks in advance.
You can download the file, save it and then use the following:
Path path = Paths.get(resource.getURI());
String contentType = Files.probeContentType(path);
This should give you the content type. Look over here.

How should I display a pdf file in browser using Spring web app?

How should I display this byte code into the WebPage of my app?
#RequestMapping(value="/getPdf", method=RequestMethod.POST)
public ResponseEntity<byte[]> getPDF1() {
String PATH_FILE = "C:\\Users\\rohit\\Downloads\\pdf_view\\sample.pdf";
Path path = Paths.get(PATH_FILE);
byte[] pdfContents = null;
try {
pdfContents =Files.readAllBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "pdf1.pdf";
headers.add("content-disposition", "inline;filename=" + filename);
headers.setContentDispositionFormData(filename, filename);
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(pdfContents, headers, HttpStatus.OK);
return response;
}
I simply want to display my PDF file in my web application.
if you simply want to display your pdf file in your web application you can just drag you pdf into your solution and use href="" to show it I think.
ps: not sure

How to download excel file in spring boot using HttpHeaders?

I am getting a resulting file but in the response I am getting gibberish symbols
here is the code I am trying
public ResponseEntity<InputStreamResource> getExcel(String filePath) throws Exception {
try {
Path excelPath = Paths.get(filePath);
byte[] excel = Files.readAllBytes(excelPath);
ByteArrayInputStream excelToByte = new ByteArrayInputStream(excel);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.add("Content-Disposition", "attachment; filename=ABCGeneratedExcel.xls");
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new InputStreamResource(excelToByte));
}
catch (NoSuchFileException e) {
System.out.prinln("does not exist");
}
You should use HttpServletResponse instead. And let Spring framework initialize it by declaring as Controller method's parameter. Because you will write the excel file as binary stream, do not define the return type.
Then write the response stream after setting the contentType and header for excel downloading.
public void getExcel(String filePath, HttpServletResponse response) {
byte[] excel = Files.readAllBytes(excelPath);
String fileName = "anyFileName.xlsx"
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.getWriter().write(excel); // in fact, you need to surround this by try-catch block
}
Path filePath = pathToFolder.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return resource;
} else {
throw new NotFoundException(String.format("File %s not found", fileName));
}
Where path to File - in your directory, and file name - name of file in your directory.
Next step is:
Resource resource = service.downloadFile(fileName);
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException e) {
log.info("Could not determine file type");
}
if (contentType == null) {
contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
}
return ResponseEntity
.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(
"%s; filename=%s", content.name().toLowerCase(), resource.getFilename()
)
)
.body(resource);
Where first %s - attachment - for downloading, and inline - for rendering file in the browser.
Second %s - name of file (note that if you are storing your file in the file system, use file name with extension).

What should I modify such that browser gives me the option to save the returned file?

#GetMapping(value = "/draftReport", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public void generateDraftResport(#RequestParam("schoolID") String schoolID, HttpServletResponse response) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
response.setHeader("Content-Disposition", "attachment; filename=" + "draft_export.xlsx");
try {
InputStream is = exportHandler.draftReport(schoolID);
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
System.out.println("Successfully written");
}
catch (IOException ex) {
log.info("Error writing file to output stream. " + ex);
System.out.println("Error while writing file");
}
}
The draftReport method returns an InputStream containing the XSSFWorkbook data. On invoking my Api '/draftReport', I want that file to be available to the browser to save. What am I missing, if at all? I get all the success logs, but no download popup.

error displaying image in IE10

Server:
#RequestMapping(value = "/url/{size}/{id}", method = RequestMethod.GET)
public void getPortfolioFile(HttpServletResponse response,
#PathVariable("id") int id,
#PathVariable("size") int size)
{
File img = provider.getImage(id, size);
if (img != null) {
try {
FileCopyUtils.copy(FileCopyUtils.copyToByteArray(img), response.getOutputStream());
String mimeType = img.toURL().openConnection().getContentType();
response.setContentType(mimeType);
response.setContentLength((int) img.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + img.getName() + "\"");
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
html:
<img src="/url/2/${id}" onerror="$('#c').empty();" />
the problem is that IE10 don't display image. response body contains image, headers is 200 OK. whan can it be?
check in:
Chrome v43.0.2357.132
FireFox Developer Edition v40
IE v10
You need to set the headers before you write the content, else they are ignored.
String mimeType = img.toURL().openConnection().getContentType();
response.setContentType(mimeType);
response.setContentLength((int) img.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Content-Disposition", "attachment;
FileCopyUtils.copy(FileCopyUtils.copyToByteArray(img), response.getOutputStream());
EDIT:
you content-type "binary/octet-stream" does not make sense.
Here I would expect a "image/gif" or other appropriate content type.
I also would eliminate the content-disposition header.

Categories

Resources