ResponseEntity results in additional underscore ( _ ) in filename's extension - spring

I have a GET mapping like below:
#RequestMapping(value = "/downloadDocumentById/{symName}/{docId}", method = RequestMethod.GET)
public ResponseEntity<FileSystemResource> downloadStuff(#PathVariable String symName, #PathVariable String docId)
throws IOException {
File newFile = null;
String fullPath = documentService.getDocumentById(symName, docId).getName();
newFile = new File(fullPath);
System.out.println("newFile_Name:" + newFile.getName());
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
respHeaders.setContentLength(newFile.length());
respHeaders.setContentDispositionFormData("attachment; filename=" + newFile.getName(), null);
return new ResponseEntity<FileSystemResource>(new FileSystemResource(newFile), respHeaders, HttpStatus.OK);
}
The sysout shows the newFile_Name as sample1.pdf but not sure why my return statement is downloading the filename as sample1.pdf_
What am I doing wrong here? Or how can I fix it?

Related

SpringBoot REST produces pdf

I want to generate a dynamic PDF from a SpringBoot REST endpoint. The below generates a file but not a PDF. Any pointers in how to get a PDF file by altering the below code. Thanks in advance.
#GetMapping(value = "/generatePDF", produces = "application/pdf")
#SneakyThrows
public ResponseEntity<InputStreamResource> generatePDF(HttpServletRequest httpRequest,
HttpServletResponse response) {
String str = "Some test data goes here...";
byte[] pdf = str.getBytes();
File file = new File("C:\\test\\test.pdf");
FileUtils.writeByteArrayToFile(file, pdf);
FileInputStream fileInputStream = new FileInputStream(file);
return ResponseEntity.ok().contentLength(file.length())
.contentType(MediaType.APPLICATION_PDF)
.header("content-disposition", "filename=report.pdf")
.body(new InputStreamResource(fileInputStream));
try this
#GetMapping(value = "/generatePDF", produces = "application/pdf")
#SneakyThrows
public ResponseEntity<byte[]> generatePDF(HttpServletRequest httpRequest, HttpServletResponse response) {
String str = "Some test data goes here...";
byte[] pdf = str.getBytes();
File file = new File("C:\\test\\test.pdf");
FileUtils.writeByteArrayToFile(file, pdf);
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_OCTET_STREAM);
header.setContentLength(pdf.length);
header.set("Content-Disposition", "attachment; filename=" + "pdf-" + id + ".pdf");
return new ResponseEntity<>(pdf, header, HttpStatus.OK);
}

How to convert collection to csv with jackson in java spring?

I have a problem to convert a java.util.Collection to a csv file with jackson.
In the following code you can see a method to convert the collection to a csv-string.
But i need a method to convert the collection with com.fasterxml.jackson.
The Enum "DownloadType" get the column and headerlines for csv file.
Do you have an idea to fix them?
#RequestMapping(value = "/csv",
produces = {"text/csv"},
consumes = {"application/json"},
method = RequestMethod.POST)
public ResponseEntity<Object> exportCsv()
{
ResponseEntity<Object> response = null;
try
{
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, "text/csv; charset=UTF-8");
headers.add(HttpHeaders.CACHE_CONTROL, "no-store, must-revalidate");
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=\"export.csv\"");
headers.add(HttpHeaders.EXPIRES, "0");
byte[] csvBytes = null;
byte[] headerBytes = null;
byte[] lineBytes = null;
CsvMapper mapper = new
Collection<User> users = getUsers()
headerBytes = DownloadType.USER.getHeaderLine().getBytes("UTF-8");
lineBytes = mapper.writer(DownloadType.USER.getCsvSchema()).writeValueAsBytes(users);
if (headerBytes != null && lineBytes != null)
{
csvBytes = new byte[headerBytes.length + lineBytes.length];
System.arraycopy(headerBytes, 0, csvBytes, 0, headerBytes.length);
System.arraycopy(lineBytes, 0, csvBytes, headerBytes.length, lineBytes.length);
}
response = new ResponseEntity<>(csvBytes, headers, HttpStatus.OK);
}
catch (Exception e)
{
LOG.error(e.getMessage(), e);
}
return response;
}
Maybe try something like this. By writing the data directly to the servlet response the string will get returned directly back to the client as is without formatting or post-processing.
#RequestMapping(value = "/csv",
produces = {"text/csv"},
consumes = {"application/json"},
method = RequestMethod.POST)
public void exportCsv(HttpServletResponse response)
{
...
String headerString = DownloadType.USER.getHeaderLine()
String data = mapper.writer(DownloadType.USER.getCsvSchema()).writeValueAsString(users);
response.setContentType("text/plain; charset=utf-8");
response.getWriter().print(headerString);
response.getWriter().print(data);
Adapted from:
How to Return CSV Data in Browser From Spring Controller

File upload with in Spring MVC without adding any additional parameter in controller method

I am using spring boot 2. My new task is file uploading. I already did it. But I am asked to do it without adding a additional parameter to controller method like #RequestParam("files") MultipartFile files[]. I want to get this from request instead of adding this parameter.
How can I solve this?
I am adding my current code following.
#RequestMapping(value="/uploadMultipleFiles", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload( #RequestParam("files") MultipartFile files[]){
try {
String filePath="c:/temp/kk/";
StringBuffer result=new StringBuffer();
byte[] bytes=null;
result.append("Uploading of File(s) ");
for (int i=0;i<files.length;i++) {
if (!files[i].isEmpty()) {
bytes = files[i].getBytes();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(filePath+files[i].getOriginalFilename())));
stream.write(bytes);
stream.close();
result.append(files[i].getOriginalFilename() + " Ok. ") ;
}
else
result.append( files[i].getOriginalFilename() + " Failed. ");
}
return result.toString();
} catch (Exception e) {
return "Error Occured while uploading files." + " => " + e.getMessage();
}
}
You can get files from HttpRequest:
#RequestMapping(value="/uploadMultipleFiles", method=RequestMethod.POST)
public String handleFileUpload(HttpRequest request){
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> yourFiles = multipartRequest.getFileMap();
return "All is Ok!";
}
My sample code.
#RequestMapping(value = "/multiple/upload", method = RequestMethod.POST)
public #ResponseBody String test(#RequestParam(value = "files[]") List<MultipartFile> files,
HttpServletRequest req) {
MultipartFileWriter writer = new MultipartFileWriter();
String folderPath = "/file/";
for (MultipartFile file : files) {
writer.writeFile(file, folderPath, req);
}
return "success";
}

GridFSDBFile cannot be cast to org.springframework.web.multipart.MultipartFile

I'm coding a spring mvc webapp that uses images of type MultipartFile which i convert to byte[] and then to Inputstream and store it in MongoDB using GridFsTemplate.
Now the problem is I want to display the stored images in a webpage but whenever I try to, the database returns the image file as GridFSDBFiles and so tosses the following exception:
java.lang.ClassCastException: com.mongodb.gridfs.GridFSDBFile cannot be cast to org.springframework.web.multipart.MultipartFile
This is my DAO for storing images:
public void saveScan(Scan scan) throws IOException {
String owner = String.valueOf(scan.getPatientId());
String fileName = String.valueOf(scan.getPatientId() + "" + scan.getScanType());
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/YYYY HH:mm a");
String uploadTime = simpleDateFormat.format(date);
System.out.println("the scan type is " + scan.getScanType());
DBObject metaData = new BasicDBObject();
metaData.put("owner", owner);
metaData.put("fileName", fileName);
metaData.put("uploadTime", uploadTime);
byte[] scanBytes = scan.getScan().getBytes();
InputStream inputStream = new ByteArrayInputStream(scanBytes);
scanDaoImpl.SaveScan(inputStream, fileName, "image/jpeg", metaData);
}
And this is for retrieving the images:
public MultipartFile findOneScan(BigInteger patientId) {
MultipartFile multipartFile = (MultipartFile) gridFsTemplate
.findOne(new Query(Criteria.where("metadata.owner").is(patientId)));
return multipartFile;
And this is my controller for getting images
#ResponseBody
#RequestMapping(value = "/patients/{id}/scan", produces = MediaType.IMAGE_JPEG_VALUE)
public ResponseEntity<byte[]> scanImage(#PathVariable("id") BigInteger id) throws IOException {
logger.debug("scanImage() is finding Image to display");
byte[] bs = patientScanServiceImpl.findOne(id).getBytes();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.IMAGE_JPEG);
httpHeaders.setCacheControl(CacheControl.noCache().getHeaderValue());
return new ResponseEntity<byte[]>(bs, httpHeaders, HttpStatus.OK);
}
This is my thymeleaf image tag:
<span>
<img th:src="#{/patients/{patientid}/scan(patientid=${patient.id})}" width="250" height="250"/>
</span>
Now I have more insight in this, and I have finally found a solution. You cannot directly cast a gridFSDBFile straight to byte[ ]; it must first be converted to OutputStream and then byte[ ] if it must be displayed. So I allowed my DAO method to return a GridFSDBFile but in the service layer I converted the GridFSDBFile to ByteArrayOutputStream and then to byte[ ].
Now my DAO method for retrieving images is
public GridFSDBFile findOneScan(BigInteger patientId, String scanType) {
String fileName = String.valueOf(patientId + "" + scanType);
GridFSDBFile gridFSDBFile = gridFsTemplate.findOne(new Query(Criteria.where("metadata.fileName").is(fileName)));
return gridFSDBFile;
And my service layer which feeds the controller is
public byte[] findOne(BigInteger patientId, String scanType) throws IOException {
GridFSDBFile gridFSDBFile = scanRepository.findOneScan(patientId, scanType);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
gridFSDBFile.writeTo(outputStream);
byte[] bs = outputStream.toByteArray();
return bs;
}
And the whole thing works fine.

Spring Restful Mutipart

I would like to ask information regarding Multipart/Form-data, if these are compatible with RequestMethod.GET?
In my case I have to return a file + JSON in one response. (Note: File should not be inside the JSON). Sample response:
FILE
{
"id":"1234",
"name":"question Man"
}
I think this might be helpful, please modify it as of your needs.
#RequestMapping(value = URIConstansts.GET_FILE, produces = { "application/json" }, method = RequestMethod.GET)
public #ResponseBody ResponseEntity getFile(#RequestParam(value="fileName", required=false) String fileName,HttpServletRequest request) throws IOException{
ResponseEntity respEntity = null;
byte[] reportBytes = null;
File result=new File("/filepath/"+fileName);
if(result.exists()){
InputStream inputStream = new FileInputStream("/filepath/"+fileName);
String type=result.toURL().openConnection().guessContentTypeFromName(fileName);
byte[]out=org.apache.commons.io.IOUtils.toByteArray(inputStream);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("content-disposition", "attachment; filename=" + fileName);
responseHeaders.add("Content-Type",type);
respEntity = new ResponseEntity(out, responseHeaders,HttpStatus.OK);
}else{
respEntity = new ResponseEntity ("File Not Found", HttpStatus.OK);
}
return respEntity;
}

Resources