Java Exception getOutputStream() has already been called for this response while downloading file from backend - spring

I have this code in order to download files from backend:
final File file = new File(filePath);
String fileType = Files.probeContentType(file.toPath());
response.setContentType(fileType);
response.setHeader("Content-disposition: attachment;", "filename=\"" + fileName + "\"");
response.setContentLength((int)new File(filePath).length());
final OutputStream os = response.getOutputStream();
IOUtils.copy(is, os);
response.flushBuffer();
os.flush();
os.close();
is.close();
and I get this exception in backend:
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:578)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:212)
Does anyone know what I can do in order to prevent this exception?

As far as I know you shouldn't call flush and/or close on the response outputstream
Other way would be to delegate all to Spring controller
I always use this code and I never had problems
#RequestMapping(method = { RequestMethod.GET },
value = { "/file/{idFile}" })
public ResponseEntity<InputStreamResource> downloadCsv(
#PathVariable("idFile") String idFile) {
try {
File file = new File("yourFilePath");
HttpHeaders respHeaders = new HttpHeaders();
//Add your mediaType....mine was csv
MediaType mediaType = new MediaType("text","csv");
respHeaders.setContentType(mediaType);
respHeaders.setContentLength(file.length());
respHeaders.setContentDispositionFormData("attachment", file.getName());
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
} catch (Exception e) {
String message = "Errore nel download del file "
+ idFile + ".csv; "
+ e.getMessage();
logger.error(message, e);
return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
I hope this can be useful
Angelo

Related

Download rtf file spring boot

Good afternoon.
I need to download an rtf file that was put into the database as a byte[] to the user. The application runs on the server, and it coulnd be unloaded on the client's PC. I took methods from my previous project. There it was necessary to form and unload the exel file. I tried to upgrade them for this task, but I ran into one problem.
Naturally, I can't get the MediaType for byte[].
Tell me, can I somehow explicitly specify it?
public class MediaTypeUtils {
public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {
String mineType = servletContext.getMimeType(fileName);
try {
MediaType mediaType = MediaType.parseMediaType(mineType);
return mediaType;
} catch (Exception e) {
return MediaType.APPLICATION_OCTET_STREAM;
}
} }
public static ResponseEntity<InputStreamResource> downloadFile1(ServletContext servletContext, PaymentOrderArchive archive) throws IOException {
MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(servletContext, archive.getRtffilename());
InputStream resource = null;
try (FileOutputStream stream = new FileOutputStream(archive.getRtffilename())) {
stream.write(archive.getEfile());
IOUtils.copyLarge(resource, stream);
InputStreamResource file = new InputStreamResource(resource);
return ResponseEntity.ok()
// Content-Disposition
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + archive.getRtffilename())
// Content-Type HERE
.contentType(mediaType)
// Contet-Length
.contentLength(resource.available()) //
.body(new InputStreamResource(resource));
}
}

email not send in spring

I want to send an email with spring boot that's way I'm setting this configuration in my aplication.properties :
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.host=xxxxx.hostgator.com
spring.mail.port=465
spring.mail.username=XXX#xxxx.com
spring.mail.password=XXXX
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
but the problem is when i test it with postman the request is always in the state "loading" :
when i test the function with an gmail account it works fin!
my fucntion :
public void sendPaimentEmail(String to, String subject, String text) {
MimeMessage message = emailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text, true);
FileSystemResource imageSignature = new FileSystemResource(new File(this.pathToSaveFile2 + "logo.png"));
if (null != imageSignature && imageSignature.exists()) {
helper.addInline("logo", imageSignature);
}
FileSystemResource file = new FileSystemResource(new File(this.pathToSaveFile2 + "historique.png"));
helper.addAttachment("Invoice", file);
this.emailSender.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}

Download file, spring boot e angular 2

Would you help me?
Hi, I'm having the same problem.
public FileSystemResource patch(#RequestBody List<Especie> especies, HttpServletResponse response) {
filename=\"somefile.pdf\"");
response.setContentType("application/vnd.ms-excel");
response.setHeader("content-disposition", "attachment; filename="+"nomeArquivo"+".xls");
// return new FileSystemResource(new File("xxx"));
Preconditions.checkNotNull(especies);
List<String> nameColumns = especies.get(0).getColumns();
List<IExcel> list = castList(especies);
// List resource = this.service.exportFileExcel(list, nameColumns, response);
File retorno = this.service.exportFileExcel(list, nameColumns, response);
return new FileSystemResource(retorno);
// response.setContentLength(bytes.length); // opcional
// response.getOutputStream().write(bytes);

spring : get response as Multipart File from REST WebService

I am creating POC for RESTFUL Web service using Spring 4.0. Requirement is to receive MultipartFile as Response from REST WEB-Service.
REST Service Controller
#RequestMapping(value="/getcontent/file", method=RequestMapping.post)
public MultipartFile getMultipartAsFileAsObject() {
File file = new File("src/test/resources/input.docx");
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file",file.getName(),
"application/docx", IOUtils.toByteArray(input));
return multipartFile
}
I call this service using third party Clients and Apache Http Client as well. kindly have a look on output.
Using Third party REST client ie. Postman
output looks like Json -
{
"name" : "file",
"originalfilename" : "sample.docx",
"contentType" : "application/docx",
"content" : [
82,
101,
97,
100,
101,
32,
32,
.
.
.
.
.
]
}
Apache HTTP Client Sample code
private static void executeClient() {
HttpClient client = new DefaultHttpClient();
HttpPost postReqeust = new HttpPost(SERVER_URI);
try{
// Set Various Attributes
HttpResponse response = client.execute(postReqeust) ;
//Verify response if any
if (response != null)
{
InputStream inputStream = response.getEntity().getContent();
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream outputStream = new FileOutputStream
(new File("src/main/resource/sample.docx"));
outputStream.write(buffer);
outputStream.flush();
outputStream.close();
}
}
catch(Exception ex){
ex.printStackTrace();
}
Output of Apache Http client
file is getting Created but It is empty. (0 bytes).
I found some interesting answers from multiple stackoverflow questions.
Links are given below
file downloading in restful web services
what's the correct way to send a file from REST web service to client?
For Sending single file : (copied from above sources)
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // Initialize this to the File path you want to serve.
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
For Sending Zip file : (copied from above sources)
1) Approach First :
You can use above method to send any file / Zip.
private static final String FILE_PATH = "d:\\Test2.zip";
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = new File(FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=newfile.zip");
return response.build();
}
2) Approach Second :
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput helloWorldZip() throws Exception {
return new StreamingOutput(){
#Override
public void write(OutputStream arg0) throws IOException, WebApplicationException {
// TODO Auto-generated method stub
BufferedOutputStream bus = new BufferedOutputStream(arg0);
try {
Thread.currentThread().getContextClassLoader().getResource("");
File file = new File("d:\\Test1.zip");
FileInputStream fizip = new FileInputStream(file);
byte[] buffer2 = IOUtils.toByteArray(fizip);
bus.write(buffer2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}

Multipart/form-data and boundary. Need help in streaming the data at server end

I have multipart/form-data request from client side which will upload multiple files. Each file would be a large file (more than 10MB in size). I want to receive each file individually and process it while remaining files are still getting received completely.
This is my request in rest console
URL : http://localhost:8080/multiUpload
Content-Type : multipart/form-data;boundary=myboundary
form-data : two attachments
This is my snippet of code to handle it.
#RequestMapping(value = "/multiUpload", method = RequestMethod.POST)
public #ResponseBody String handleMultiFileUpload(HttpServletRequest request)
throws IOException {
System.out.println("======Inside handleFileUpload======");
try {
MultipartStream multipartStream = new MultipartStream(
request.getInputStream(), "myboundary".getBytes(),
1024 * 1024, null);
boolean nextPart = multipartStream.skipPreamble();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
while (nextPart) {
System.out.println("inside while");
multipartStream.readBodyData(outputStream);
InputStream inputStream = new ByteArrayInputStream(
outputStream.toByteArray());
nextPart = multipartStream.readBoundary();
}
} catch (MultipartStream.MalformedStreamException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "You successfully uploaded !";
}
The code is not entering into while loop. i.e skipPreamble is returning false. Am I doing anything wrong ??.

Resources