Why files are downloading instead of viewing in browser - java

#RequestMapping( value= "/get/{imageName}",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE ,method = RequestMethod.GET)
public ResponseEntity<byte[]> getImage1(#PathVariable("imageName") String imageName) throws IOException {
final Optional<ImageModel> retrievedImage = imageModelRepository.findByName(imageName);
ImageModel img = new ImageModel(retrievedImage.get().getName(), retrievedImage.get().getType(),retrievedImage.get().getPicByte());
byte[] imageArray= retrievedImage.get().getPicByte();
return ResponseEntity.ok().body(imageArray);
}

Content-Type of application/octet-stream forces it to always download.
You can try something like follows:
...
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("image/jpeg"));
...
headers.add("Content-Disposition", "inline; filename=" + fileName);
...
ResponseEntity<byte[]> returnValue = new ResponseEntity<>(imageArray, headers, HttpStatus.OK);
return returnValue;

Related

How to return byte[] as multipartFile as response to UI?

The attachment is already stored in the database. The Api which I was trying to achieve is getting the attachment Id as input and sending the respective byte[] as multipartFile as response to UI.
The current code snippet is:
#RequestMapping(method = { RequestMethod.POST }, value = "/getData", produces = MediaType.MULTIPART_FORM_DATA_VALUE)
#ResponseBody
public ResponseEntity<MultiValueMap<String, Object>> getAttachmentDetails(#RequestBody Integer attachmentId) {
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<String, Object>();
byte[] result = emailIntakeService.getAttachmentDetails(attachmentId);
formData.add("file", result);
return new ResponseEntity<>(formData,HttpStatus.OK);
}
the response : file=%5BB%4011a93325
Can someone help how to send byte[] as multipartFile as reponse.
You could try like this
#RequestMapping(method = { RequestMethod.POST }, value = "/getData")
#ResponseBody
public ResponseEntity<byte[]> getAttachmentDetails(#RequestBody Integer attachmentId) {
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<String, Object>();
byte[] result = emailIntakeService.getAttachmentDetails(attachmentId);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + "filename.xls" + "\"")
.body(result);
}

StreamingResponseBody returning empty file

I'm trying to create a rest service to download files from a repository, using Springboot.
I'm trying to return a ResponseEntity with StreamingResponseBody, to return the file that i get from the repository, as an InputStream.
This is the current code i have:
#GetMapping(path = "/downloadFile")
public ResponseEntity<StreamingResponseBody> downloadFile(#RequestParam(value = "documentId") String documentId,
HttpServletRequest request, HttpServletResponse response) throws InterruptedException, IOException {
InputStream is = downloadService.getDocument(documentId);
StreamingResponseBody out = outputStream -> {
outputStream.write(IOUtils.toByteArray(is));
};
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "text/csv");
headers.add("Content-Disposition", "attachment; filename=" + documentId);
headers.add("Pragma", "no-cache");
headers.add("Cache-Control", "no-cache");
return (new ResponseEntity<>(out, headers, HttpStatus.OK));
}
When I consume this endpoint, using directly the browser, or postman, the file that is downloaded comes empty.
I understand that the OutputStream is written to asynchronously (Async is enabled in the config class).
How can I consume this service and get the file completely written, the way it comes from the repository I'm using ? ( if possible using Postman, just for testing purposes)
Am i building the service correctly?
I have modified the code bit little, in my documentId is the name of the file to be downloaded. I have tested, it is working fine. Check below the code.
#GetMapping(path = "/downloadFile")
public ResponseEntity<StreamingResponseBody> downloadFile(
#RequestParam(value = "documentId") String documentId,
HttpServletRequest request,
HttpServletResponse response)
throws InterruptedException, IOException {
String dirPath = "E:/sure-delete/"; //Directory having the files
InputStream inputStream = new FileInputStream(new File(dirPath + documentId));
final StreamingResponseBody out =
outputStream -> {
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
System.out.println("Writing some bytes of file...");
outputStream.write(data, 0, nRead);
}
};
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "text/csv");
headers.add("Content-Disposition", "attachment; filename=" + documentId);
headers.add("Pragma", "no-cache");
headers.add("Cache-Control", "no-cache");
return ResponseEntity.ok().headers(headers).body(out);
}

Download a pdf using ajax and spring mvc doesn't work

I'm trying to implement an ajax download. This is my code for the ajax request:
$('#download').click(function(){
$.ajax({
url: '${downloadPath}',
type: 'GET',
data: {${_csrf.parameterName}:'${_csrf.token}'},
success: function (res) {
}
});
});
And this is my controller's method:
#Secured("IS_AUTHENTICATED")
#RequestMapping(value="download/{id}", method=RequestMethod.GET, produces="application/pdf")
#ResponseBody
public void download(#PathVariable(value="id") final Long id, HttpServletResponse response) throws IOException {
CheckList checkList = checkListService.findById(id);
// byte[] byteItem = checkListService.getFileByIdDocument(id);
File f = new File(VariabiliGlobali.PATH_CHECKLIST+checkList.getPratica().getId()+"/"+id);
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/pdf");
response.setContentLength((int)f.length());
response.setHeader("Content-Disposition", "attachment; filename=\"" + f.getName() + "\"");
FileInputStream in = new FileInputStream(f);
byte[] buffer = new byte[4096];
int length;
while( (length = in.read(buffer) ) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.flush();
}
I can see the pdf inside the response:
But my browser (Chrome) doens't do anything.
Where am I wrong? How can I dowload it?
You don't need ajax and you are using as content type application/octet-stream as we can see in your code here:
response.setContentType("application/octet-stream");
If you want to display the pdf inside the browser (if the browser has the proper plugin to read pdf) you should use:
the right pdf content type
set the proper header
In my code i did the following:
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=pdfFileName.pdf;");
In any case I'd suggest to yuo to use the "spring" way like this:
#Secured("IS_AUTHENTICATED")
#RequestMapping(value="download/{id}", method=RequestMethod.GET)
public ResponseEntity<InputStreamResource> download(#PathVariable(value="id") final Long id) throws IOException {
HttpHeaders respHeaders = new HttpHeaders();
MediaType mediaType = new MediaType("application","pdf");
respHeaders.setContentType(mediaType);
respHeaders.setContentDispositionFormData("inline", "pdfFileName.pdf");
//Here you have to take the InputStream of the file you want to download
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}
I hope it's useful
Angelo
Set your content type in header. So browsers handles the pdf.
headers.setContentType(MediaType.parseMediaType("application/pdf"));
Below is the sample code.
#Secured("IS_AUTHENTICATED")
#RequestMapping(value="download/{id}", method=RequestMethod.GET, produces="application/pdf")
public ResponseEntity<?> download(#PathVariable(value="id") final Long id, HttpServletResponse response) throws IOException {
List<SampleDto> reportData = new ArrayList<SampleDto>();
HttpHeaders headers = new HttpHeaders();
if (null == reportData || reportData.size() == 0) {
return new ResponseEntity<byte[]>(null, headers, HttpStatus.NO_CONTENT);
}
byte[] contents = writePdfContentToBytes();//Here you should your code to get content in bytes.
headers.setContentType(MediaType.parseMediaType("application/pdf"));
headers.setContentDispositionFormData("inline", "Report.pdf");
return new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
}

"Content-Disposition" and file name in headers with AngularJS

I use angularjs 1.3.14
I have a java REST services produce a xml file with this header: "Content-Disposition", "attachment; filename=yourFileName";
I need take the file with the name of my file on AngularJS.
I have this code:
$http.get('/someUrl').success(function(data, status, headers){
var myHeaders = headers();
...
});
but in myHeaders have only {content-type="application/xml"}. I need find "Content-Disposition", "attachment; filename=yourFileName"
Java Services:
#GET
#Path(EXPORT_URL)
#Produces(MediaType.APPLICATION_XML)
public Response export(#Context HttpServletRequest request) {
String userName = request.getRemoteUser();
if (userName != null) {
...
ResponseBuilder response = Response.ok(myObject);
response.header("Content-Disposition", "attachment; filename=myFile.xml");
return response.build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
}
2 years after, I find a solution:
#RequestMapping(value = "/export", method = RequestMethod.GET, produces = MediaType.APPLICATION_XML)
public ResponseEntity<String> export(...
HttpHeaders headers = new HttpHeaders();
headers.setAccessControlExposeHeaders(Collections.singletonList("Content-Disposition"));
headers.set("Content-Disposition", "attachment; filename=" + filename);
return new ResponseEntity<>(exportedContent, headers, HttpStatus.OK);
This is a server side CORS issue. You need to enable this:
"Access-Control-Expose-Headers", "Content-Disposition"

How to set 'Content-Disposition' and 'Filename' when using FileSystemResource to force a file download file?

What is the most appropriate, and standard, way to set the Content-Disposition=attachment and filename=xyz.zip using Spring 3 FileSystemResource?
The action looks like :
#ResponseBody
#RequestMapping(value = "/action/{abcd}/{efgh}", method = RequestMethod.GET, produces = "application/zip")
#PreAuthorize("#authorizationService.authorizeMethod()")
public FileSystemResource doAction(#PathVariable String abcd, #PathVariable String efgh) {
File zipFile = service.getFile(abcd, efgh);
return new FileSystemResource(zipFile);
}
Although the file is a zip file so the browser always downloads the file, but I would like to explicitly mention the file as attachment, and also provide a filename that has nothing to do with the files actual name.
There might be workarounds for this problem, but I would like to know the proper Spring and FileSystemResource way to achieve this goal.
P.S. The file that is being used here is a temporary file, marked for deletion when the JVM exists.
In addition to the accepted answer, Spring has the class ContentDisposition specific for this purpose. I believe it deals with the file name sanitization.
ContentDisposition contentDisposition = ContentDisposition.builder("inline")
.filename("Filename")
.build();
HttpHeaders headers = new HttpHeaders();
headers.setContentDisposition(contentDisposition);
#RequestMapping(value = "/action/{abcd}/{efgh}", method = RequestMethod.GET)
#PreAuthorize("#authorizationService.authorizeMethod(#id)")
public HttpEntity<byte[]> doAction(#PathVariable ObjectType obj, #PathVariable Date date, HttpServletResponse response) throws IOException {
ZipFileType zipFile = service.getFile(obj1.getId(), date);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
response.setHeader("Content-Disposition", "attachment; filename=" + zipFile.getFileName());
return new HttpEntity<byte[]>(zipFile.getByteArray(), headers);
}
#RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
#ResponseBody
public FileSystemResource getFile(#PathVariable("file_name") String fileName,HttpServletResponse response) {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=somefile.pdf");
return new FileSystemResource(new File("file full path"));
}
Here is an alternative approach for Spring 4. Note that this example clearly does not use good practices regarding filesystem access, this is just to demonstrate how some properties can be set declaratively.
#RequestMapping(value = "/{resourceIdentifier}", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
// #ResponseBody // Needed for #Controller but not for #RestController.
public ResponseEntity<InputStreamResource> download(#PathVariable(name = "resourceIdentifier") final String filename) throws Exception
{
final String resourceName = filename + ".dat";
final File iFile = new File("/some/folder", resourceName);
final long resourceLength = iFile.length();
final long lastModified = iFile.lastModified();
final InputStream resource = new FileInputStream(iFile);
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=" + resourceName)
.contentLength(resourceLength)
.lastModified(lastModified)
.contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE)
.body(resource);
}
Made few changes to both given answers and I ended up with the best of both in my project where I needed to extract an image from the database as a blob and then serve it to the clients :
#GetMapping("/images/{imageId:.+}")
#ResponseBody
public ResponseEntity<FileSystemResource> serveFile(#PathVariable #Valid String imageId,HttpServletResponse response)
{
ImageEntity singleImageInfo=db.storage.StorageService.getImage(imageId);
if(singleImageInfo==null)
{
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
Blob image=singleImageInfo.getImage();
try {
String filename= UsersExtra.GenerateSession()+"xxyy"+singleImageInfo.getImage1Ext().trim();
byte [] array = image.getBytes( 1, ( int ) image.length() );
File file = File.createTempFile(UsersExtra.GenerateSession()+"xxyy", singleImageInfo.getImage1Ext().trim(), new File("."));
FileOutputStream out = new FileOutputStream( file );
out.write( array );
out.close();
FileSystemResource testing=new FileSystemResource(file);
String mimeType = "image/"+singleImageInfo.getImage1Ext().trim().toLowerCase().replace(".", "");
response.setContentType(mimeType);
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", filename);
response.setHeader(headerKey, headerValue);
// return new FileSystemResource(file);
return ResponseEntity.status(HttpStatus.OK).body( new FileSystemResource(file));
}catch(Exception e)
{
System.out.println(e.getMessage());
}
return null;
}
Using a ResponseEntity in Kumar's code will help you respond with the correct Response code.
Note: converting from a blob to a file is quoted from this link:
Snippet to create a file from the contents of a blob in Java

Categories