corrupted PDF file downloaded from spring rest api - spring

I am developing a rest end point to download a existing pdf file. I'm able to download PDF with size, but when I open, getting error as
'Adobe reader couldnot open it is either not supported file type or
because file has been damaged'.
I have noticed that in postman, response header content type is application/pdf;charset=UTF-8. I'm not sure if this is the cause.
With simple spring boot application I'm able to download, but in our project when I implement the same code, it is not working.
#GetMapping( path= "/s3/downloads")
public ResponseEntity<byte[]> downloadFile()
{
InputStream in = getClass().getResourceAsStream("/com/consulting/cloud/filetransfers/rest/template_attendance_en_green_full.pdf");
byte[] generatedCertificate = null;
String downloadFileName = "pdfFile1.pdf";
ResponseEntity<byte[]> responseEntity = ResponseEntity.status( HttpStatus.NO_CONTENT ).body( generatedCertificate );
try {
generatedCertificate = StreamUtils.copyToByteArray(in);
HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Allow-Origin", "*");
headers.setContentType( MediaType.APPLICATION_PDF );
headers.setContentLength( generatedCertificate.length );
headers.setContentDispositionFormData( "attachment", downloadFileName );
responseEntity = ResponseEntity.ok().headers( headers ).body( generatedCertificate );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseEntity;
}
The file is opened as expected.

Related

Saving an image to a newly created folder with Uri?

The app i am creating is supposed to save a picture in a sub folder of the pictures folder. As long as i save the picture to the base folder it works fine, but it returns an error as soon as i try to target the subfolder. Permission for writing/reading external storage are given. Do i need to create the folder another way to use it? How do i get the URI of the folder itself?
The error for v1 is: "Failed to write destination file".
The error for v2 is: "Unknown or unsupported URL:content://media/external/images/media/ProxF/"
private void captureImage(ImageCapture imageCapture)
{
//Folder
File dir = new File(getExternalStoragePublicDirectory(DIRECTORY_PICTURES) +"/ProxF");
try{
if(dir.mkdir()) {
System.out.println("Directory created");
} else {
System.out.println("Directory is not created");
}
}catch(Exception e){
e.printStackTrace();
}
//MEDIA API
String FotoString="picture1";
ContentValues contentValues=new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, FotoString);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
//Saving to the picture folder - working
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
//V1 - not working
File folder = new File(getExternalStoragePublicDirectory(DIRECTORY_PICTURES).toString() + "/ProxF/");
Uri uri1=Uri.fromFile(folder);
//V2 - not working
Uri uri2 = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI+"/ProxF/")
ImageCapture.OutputFileOptions fileOptions= new ImageCapture.OutputFileOptions.Builder(getContentResolver(),uri,contentValues).build();
imageCapture.takePicture(fileOptions, Executors.newCachedThreadPool(), new ImageCapture.OnImageSavedCallback() {
#Override
public void onImageSaved(#NonNull ImageCapture.OutputFileResults outputFileResults) {
runOnUiThread(() -> Toast.makeText(KameraAc.this, "Image Saved ",Toast.LENGTH_SHORT).show());
startCamera();
}
#Override
public void onError(#NonNull ImageCaptureException exception) {
runOnUiThread(() -> Toast.makeText(KameraAc.this, "Failed to save: "+exception.getMessage(), Toast.LENGTH_SHORT).show());
startCamera();
}
});
}

How to read and write files in a reactive way using InputStreamand OutputStream

I am trying to read an Excel file in manipulate it or add new data to it and write it back out. I am also trying to do this a complete reactive process using Flux and Mono. The Idea is to return the resulting file or bytearray via a webservice.
My question is how do I get a InputStream and OutputStream in a non blocking way?
I am using the Apache Poi library to read and generate the Excel File.
I currently have a solution based around a mix of Mono.fromCallable() and Blocking code getting the Input Stream.
For example the webservice part is as follows.
#GetMapping(value = API_BASE_PATH + "/download", produces = "application/vnd.ms-excel")
public Mono<ByteArrayResource> download() {
Flux<TimeKeepingEntry> createExcel = excelExport.createDocument(false);
return createExcel.then(Mono.fromCallable(() -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
excelExport.getWb().write(outputStream);
return new ByteArrayResource(outputStream.toByteArray());
}).subscribeOn(Schedulers.elastic()));
}
And the Processing of the file:
public Flux<TimeKeepingEntry> createDocument(boolean all) {
Flux<TimeKeepingEntry> entries = null;
try {
InputStream inputStream = new ClassPathResource("Timesheet Template.xlsx").getInputStream();
wb = WorkbookFactory.create(inputStream);
Sheet sheet = wb.getSheetAt(0);
log.info("Created document");
if (all) {
//all entries
} else {
entries = service.findByMonth(currentMonthName).log("Excel Export - retrievedMonths").sort(Comparator.comparing(TimeKeepingEntry::getDateOfMonth)).doOnNext(timeKeepingEntry-> {
this.populateEntry(sheet, timeKeepingEntry);
});
}
} catch (IOException e) {
log.error("Error Importing File", e);
}
return entries;
}
This works well enough but not very in line with Flux and Mono. Some guidance here would be good. I would prefer to have the whole sequence non-blocking.
Unfortunately the WorkbookFactory.create() operation is blocking, so you have to perform that operation using imperative code. However fetching each timeKeepingEntry can be done reactively. Your code would looks something like this:
public Flux<TimeKeepingEntry> createDocument() {
return Flux.generate(
this::getWorkbookSheet,
(sheet, sink) -> {
sink.next(getNextTimeKeepingEntryFrom(sheet));
},
this::closeWorkbook);
}
This will keep the workbook in memory, but will fetch each entry on demand when the elements of the Flux are requested.

loading a pdf in-browser from a file in the server file system?

How can I get a pdf located in a file in a server's directory structure to load in a browser for users of a Spring MVC application?
I have googled this and found postings about how to generate PDFs, but their answers do not work in this situation. For example, this other posting is not relevant because res.setContentType("application/pdf"); in my code below does not solve the problem. Also, this other posting describes how to do it from a database but does not show full working controller code. Other postings had similar problems that caused them not to work in this case.
I need to simply serve up a file (not from a database) and have it been viewable by a user in their browser. The best I have come up with is the code below, which asks the user to download the PDF or to view it in a separate application outside the browser. What specific changes can I make to the specific code below so that the user automatically sees the PDF content inside their browser when they click on the link instead of being prompted to download it?
#RequestMapping(value = "/test-pdf")
public void generatePdf(HttpServletRequest req,HttpServletResponse res){
res.setContentType("application/pdf");
res.setHeader("Content-Disposition", "attachment;filename=report.pdf");
ServletOutputStream outStream=null;
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(new File("/path/to", "nameOfThe.pdf")));
/*ServletOutputStream*/ outStream = res.getOutputStream();
//to make it easier to change to 8 or 16 KBs
int FILE_CHUNK_SIZE = 1024 * 4;
byte[] chunk = new byte[FILE_CHUNK_SIZE];
int bytesRead = 0;
while ((bytesRead = bis.read(chunk)) != -1) {outStream.write(chunk, 0, bytesRead);}
bis.close();
outStream.flush();
outStream.close();
}
catch (Exception e) {e.printStackTrace();}
}
Change
res.setHeader("Content-Disposition", "attachment;filename=report.pdf");
To
res.setHeader("Content-Disposition", "inline;filename=report.pdf");
You should also set the Content Length
FileCopyUtils is handy:
#Controller
public class FileController {
#RequestMapping("/report")
void getFile(HttpServletResponse response) throws IOException {
String fileName = "report.pdf";
String path = "/path/to/" + fileName;
File file = new File(path);
FileInputStream inputStream = new FileInputStream(file);
response.setContentType("application/pdf");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "inline;filename=\"" + fileName + "\"");
FileCopyUtils.copy(inputStream, response.getOutputStream());
}
}

Uploading more than one image

Dear All,
Working on Spring MVC. I want to upload more than one images from the client. How to achieve it. I know how to handle the multipart form data for single image. But now I am expecting some data with some images from the client.
Any help or url that will help me.
Thanks,
Op
Image is also a file. Whether you would be storing it in database / in file system but it is still a file.
In spring MVC, you could do as shown in the below link:
http://viralpatel.net/blogs/spring-mvc-multiple-file-upload-example/
Here are the code i tried and it is working fine at my end.
//Handle multiple images
#RequestMapping(method = RequestMethod.POST, value="upload", consumes=MediaType.MULTIPART_FORM_DATA_VALUE,
produces=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody JSONResponse uploadImages(HttpServletRequest req)
throws Exception {
try{
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) req;
Set set = multipartRequest.getFileMap().entrySet();
Iterator i = set.iterator();
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
String fileName = (String)me.getKey()+"_"+System.currentTimeMillis();
MultipartFile multipartFile = (MultipartFile)me.getValue();
System.out.println("Original fileName - " + multipartFile.getOriginalFilename());
System.out.println("fileName - " + fileName);
saveImage(fileName, multipartFile);
}
}
catch(Exception e){
e.printStackTrace();
}
return new JSONResponse();
}

How to send email with attachments

I want to send an email with an image attached with it. I am using spring 3 with velocity templates. I am able to do that but for some reasons when I add an extension with the image name I don't get the email delivered.
Following is the code I am using for it:
private MimeMessage createEmail(Application application, String templatePath, String subject, String toEmail, String fromEmail, String fromName) {
MimeMessage mimeMsg = mailSender.createMimeMessage();
Map<String, Object> model = new HashMap<String, Object>();
model.put("application", application);
String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templatePath, model);
text = text.replaceAll("\n", "<br>");
try {
MimeMessageHelper helper = new MimeMessageHelper(mimeMsg, true);
helper.setSubject(subject);
helper.setTo(toEmail);
if (fromName == null) {
helper.setFrom(fromEmail);
} else {
try {
helper.setFrom(fromEmail, fromName);
} catch (UnsupportedEncodingException e) {
helper.setFrom(fromEmail);
}
}
helper.setSentDate(application.getDateCreated());
helper.setText(text, true);
InputStream inputStream = servletContext.getResourceAsStream("images/formstack1.jpg");
helper.addAttachment("formstack1", new ByteArrayResource(IOUtils.toByteArray(inputStream)));
} catch (MessagingException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
return mimeMsg;
}
Using the code above I could add formstack1 as attachment but it has no extension so I don't get the formstack1.jpg image file. But when I use formstack1.jpg for the name of resource to be attached in helper.addAttachment("formstack1", new ByteArrayResource(IOUtils.toByteArray(inputStream))); as formstack1 changed to formstack1.jpg I don't get even the email delivered. I am using smtp.gmail.com and 25 for port. I do get the email sent successfully message on the console though. But the email
is never delivered.
EDIT: If I keep it like helper.addAttachment("formstack1", new ByteArrayResource(IOUtils.toByteArray(inputStream))); and change the extension from nothing to .jpg while downloading the attached image I do get the desired image.
Could someone help me understand why is it happening and how send email with 1 or more attachments using spring 3.
Thanks.
You should better use Apache Commons HtmlEMail
http://commons.apache.org/email/userguide.html

Resources