Uploading, modifying and download the same file in memory - spring

I have to create an application that allows the user upload a specific Excel file. Sumarizing, the system needs to receive the file, write something in a specific cell and return the same file modificated to the view, then, the user can download this new file.
I'm using Apache POI for modify the excel file, but I don't know how to return this file to the view.
Upload view:
<form method="POST" enctype="multipart/form-data" th:action="#{/pessoa/lote}">
<table>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
</table>
</form>
Controller: Here I don't know what I need to do, I call a method named "consultaLote" from a Service who is named "ConsultaPessoaService".
#RequestMapping(value = "/lote", method = RequestMethod.POST)
public String handleFileUpload(#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
try {
cpService.consultaLote(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
In the service, I can read and edit the file, then its generated a FileOutputStream. At this time I don't know how to continue, I need to return the file to the view using the controller, but I don't know how:
#Service
public class ConsultaPessoaService {
public FileOutputStream consultaLote(MultipartFile file) throws IOException {
DataFormatter formatter = new DataFormatter();
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
FileInputStream inputStream = new FileInputStream(convFile);
Workbook workbook = new XSSFWorkbook(inputStream);
Sheet firstSheet = workbook.getSheetAt(0);
Iterator<Row> iterator = firstSheet.iterator();
while (iterator.hasNext()) {
Row nextRow = iterator.next();
System.out.println(formatter.formatCellValue(nextRow.getCell(3)));
nextRow.getCell(3).setCellValue("test");
}
FileOutputStream outputStream = new FileOutputStream("arquivot.xlsx");
workbook.write(outputStream);
workbook.close();
outputStream.flush();
outputStream.close();
return outputStream;
}
}

You should return a byte array from consultaLote method. Method return type will be byte[] because you need this byte array to write the httpservlet outputstream.
public byte[] consultaLote(MultipartFile file) throws IOException {
//whatever changes you want, do it here. I am going to converting part
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
// before returning you can close your your ByteArrayOutputStream
//baos.close();
return baos.toByteArray();
}
Now comes to your controller. We write the byte array to OutputStream from HttpservletResponse.
#RequestMapping(value = "/lote", method = RequestMethod.POST)
public String handleFileUpload(#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes,HttpServletResponse response) {
byte[] fileBytes = null;
String reportName="yourReportName";
try {
fileBytes = cpService.consultaLote(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(fileBytes !=null){
response.setHeader("Content-Disposition", "attachment; filename=" + reportName + ".xls");
response.setContentType("application/xls");
response.getOutputStream().write(fileBytes);
response.getOutputStream().flush();
}
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
Hope this will help.

Related

EDIT IMAGE in Srping Boot Controller

In the edit section, I wrote how to make it upload the image
Thank you very much
#PostMapping("/save")
public String add(#ModelAttribute("category") Category category, RedirectAttributes ra,
#RequestParam("fileImage") MultipartFile multipartFile) throws IOException {
String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
category.setPhoto(fileName);
Category saveCategory = categoryService.save(category);
String uploadDir = "./category-logos/" + saveCategory.getId();
Path uploadPath = Paths.get(uploadDir);
if (!Files.exists(uploadPath)) {
Files.createDirectories(uploadPath);
}
try (InputStream inputStream = multipartFile.getInputStream()) {
Path filePath = uploadPath.resolve(fileName);
Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new IOException("could not save upload file: " + fileName);
}
return "redirect:/category/list";
}
#GetMapping("/edit/{id}")
public String edit(Model model, #PathVariable(name="id")Long id) {
//`**`**`**enter code here**`**`**`
}

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";
}

Should inputstream be closed explicitly when uploading file in jersey multipart?

I use Jersey multipart to upload file in controller
Here is the typical code case:
#Path("/file")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "d://uploaded/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have read many example code online, and the inputstream is not closed.
My question is that should I close the uploadedInputStream explicitly or manually? And why?

Spring MVC Thymeleaf: Displaying Buffered Image to HTML file

Can't display the image in the html file. Where did I go wrong?
#RequestMapping(value = "/image/{usr.id}", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
public #ResponseBody BufferedImage getImage(#PathVariable("usr.id") Long id) {
Attachment att = attSvc.getPicById(id);
try {
InputStream in = new ByteArrayInputStream(att.getAttachmentFile());
return ImageIO.read(in);
} catch (IOException e) {
System.out.println("ERROR:" + e);
throw new RuntimeException(e);
}
}
Please tell me if you need more references! Thank you so much.
This should solve your issue.
...
public #ResponseBody byte[] getImage(#PathVariable("usr.id") Long id) {
...
InputStream in = new ByteArrayInputStream(att.getAttachmentFile());
BufferedImage img = ImageIO.read(in);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", bao);
return bao.toByteArray();
...

Uploading file using Spring REST API

I have my controller like this, i am using POSTMAN REST client for upload pdf file. setting content-type: multipart/form-data;boundary=randomBoundaryNotInAnyOfParts
It is creating the file but not writing anything in it. Am i missing something here?
#RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
public #ResponseBody String upload(HttpServletRequest request) {
InputStream is = null;
OutputStream out = null;
try {
is = request.getInputStream();
byte[] b = new byte[1024];
out = new FileOutputStream(new File("C:\\tmp\\upload.txt"));
out.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally{
try{
if(out != null){
out.close();
}
if(is != null){
is.close();
}
}catch(IOException io){
io.printStackTrace();
}
}
return null;
}
Thanks,
Vinay
Your byte[] is empty hence it is writing nothing in the file. Get content of the request into the byte[] and then write it into file.
Or you can use BufferedWriter also it is more fast.
Thanks,
Brijesh

Resources