get content file in java - 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.

Related

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).

Provide JSON response and download file simultaneously with Spring-Boot

Requirement:
I need to create a Rest API which can allows to download a file as well as a JSON response.
I already have 2 different APIs to solve the purpose, but now I need to merge these APIs to a single one.
public ResponseEntity<InputStreamResource> downloadFile1(
#RequestParam(defaultValue = DEFAULT_FILE_NAME) String fileName) throws IOException {
MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, fileName);
System.out.println("fileName: " + fileName);
System.out.println("mediaType: " + mediaType);
File file = new File(DIRECTORY + "/" + fileName);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
// Content-Disposition
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
// Content-Type
.contentType(mediaType)
// Contet-Length
.contentLength(file.length()) //
.body(resource);
}
Above is the existing code that only return a file to download but I need a json response as well.
You need to return Multipart content. See for example
https://github.com/juazugas/spring-boot-multipart/blob/master/src/main/java/com/example/demo/server/MultiEndpoint.java
The code
#GET
#Produces("multipart/mixed")
public MultipartBody getMulti2(#QueryParam("name") String name) {
List<Attachment> attachments = new LinkedList<>();
attachments.add(new Attachment("root", "application/json", service.getEntity(name)));
attachments.add(new Attachment("image", "application/octet-stream", service.getEntityData(name)));
return new MultipartBody(attachments, true);
}

Create a file download link using Spring Boot and Thymeleaf

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

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.

I can´t open a .pdf in my browser by Java

I´m trying to open a pdf that I have created using iText library in my browser, but it fails.
This is the code I´m using to send to browser
File file = new File(path);
try{
//InputStream stream=blob.getBinaryStream();
InputStream streamEntrada = new FileInputStream(file);
//ServletOutputStream fileOutputStream = response.getOutputStream();
PrintWriter print = response.getWriter();
int ibit = 256;
while ((ibit) >= 0)
{
ibit = streamEntrada.read();
print.write(ibit);
}
response.setContentType("application/text");
response.setHeader("Content-Disposition", "attachment;filename="+name);
response.setHeader("Pragma", "cache");
response.setHeader("Cache-control", "private, max-age=0");
streamEntrada.close();
print.close();
return null;
}
catch(Exception e){
return null;
}
}
I tried with FileOutputStream but isn´t works. I´m desperate.
Thank you.
Now, I´m trying this way, but it doesn´t work:
public class MovilInfoAction extends DownloadAction{
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
//Here the creation of the PDF
//Storing data
PdfData dPdf = pdf.drawPDF(terminal);
String path = dPdf.getPath();//Path
String name = dPdf.getName()+".pdf";//Pdf´s name
String contentType = "application/pdf";//ContentType
response.setContentType(contentType);
response.setHeader("Content-Disposition","attachment; filename="+name);
response.setHeader("Cache-control", "private, max-age=0");
response.setHeader("Content-Disposition", "inline");
File file = new File(path);
byte[] pdfBytes = es.vodafone.framework.utils.Utils.getBytesFromFile(file);
return new ByteArrayStreamInfo(contentType, pdfBytes);
}
protected class ByteArrayStreamInfo implements StreamInfo {
protected String contentType;
protected byte[] bytes;
public ByteArrayStreamInfo(String contentType, byte[] bytes) {
this.contentType = contentType;
this.bytes = bytes;
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(bytes);
}
}
}
You specify the mimetype as application/text, when it should be application/pdf.
You should set the Header and ContentType before you write the data.
And set the Content Type to application/pdf.
change
response.setContentType("application/text");
to
response.setContentType("application/pdf");
and if you want your pdf to open in browser then make following change
response.setHeader("Content-Disposition", "inline");
Put the filename in double quote "
response.setHeader("Content-Disposition","attachment; filename=\"" + attachmentName + "\"");
Android Default Browser requires GET Request. It does not understand POST Request and hence cannot download the attachment. You can send a GET request as by sending GET request, it resolved my problem. Android browser generates a GET request on its own and sends it back to server. The response received after second request will be considered final by the browser even if GET request is sent on first time by the servlet.

Categories

Resources