I am trying to establish a communication between two micros, where the first one receives a petition from the frontend and contacts with another micro, which creates an excel file and sends it back to the first micro, starting the download of the file.
First, I tried to print a simple String response to check the communication between micros and that worked correctly, but the same thing for files didn't work.
Here is the code that I am following:
For Controller A:
#GetMapping(path="/test")
public void getEntities2(HttpServletRequest request, HttpServletResponse response) throws IOException {
ResponseEntity<Workbook> responseEntity = new RestTemplate()
.getForEntity("http://localhost:8080/proceso/excel", Workbook.class);
assertThat(responseEntity.getStatusCode(), equalTo(HttpStatus.OK));
response.setHeader("Content-disposition", "attachment; filename=" + "test.xls");
Workbook workbook = responseEntity.getBody();
workbook.write(response.getOutputStream());
workbook.close();
}
The second Controller (Excel file generator):
#GetMapping(path="/excel")
public ResponseEntity<Workbook> test3(HttpServletResponse response) throws Exception {
HashMap<String, ArrayList<String>> test = new HashMap<String, ArrayList<String>>();
Workbook workbook = CreateExcel.excelCreator(test);
Workbook responseFile = workbook;
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + "test.xls")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(responseFile);
}
And then the following error appears:
org.springframework.web.client.HttpClientErrorException$NotAcceptable: 406 null
I just want to receive the file in the first controller and download the Excel from localhost. Is there any way to do it? Thanks all.
I discovered the problem. The excel file is a octet-stream file so it needs to be received as a byte[] array. This is the Controller A:
#GetMapping(path="/")
public ResponseEntity<byte[]> getEntities() throws IOException {
ResponseEntity<byte[]> responseEntity = new RestTemplate()
.getForEntity("http://localhost:8080/excel", byte[].class);
assertThat(responseEntity.getStatusCode(), equalTo(HttpStatus.OK));
return responseEntity;
}
And Controller B:
#GetMapping(path="/excel")
public void getExcel(HttpServletResponse response) throws Exception {
Iterable<InstancesAggregate> list = instancesAggregate.myfindAll(); //Creating a list
HashMap<String, ArrayList<String>> test = CreateExcel.setExcelProceso(list);
Workbook workbook = CreateExcel.excelCreator(test);
response.setHeader("Content-disposition", "attachment; filename=" + "test.xls");
workbook.write(response.getOutputStream());
workbook.close();
}
This works fine for me, hope someone find the info useful.
Related
I am trying to download a file through Spring REST Controller. Below is my code -
#RequestMapping(value="/aaa",method=RequestMethod.GET,produces=MediaType.APPLICATION_OCTATE_STREAM_VALUE)
public ResponseEntity<byte[]> testMethod(#RequestParam("test") String test) {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentDispositionFromData("attachment","testExcel.xlsx");
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
File file = new File("C:\\testExcel.xlsx");
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = new ByteArrayResource(Files.readAllbytes(path));
return new ResposeEntity<byte[]>(resource.getByteArray(),responseHeaders,HttpStatus.OK);
}
This is called in a button click. After I click the button nothing happens. While debugging this java, I could see the bytestream. In developer tools of Mozilla, I could see successful HTTP response(response in bytestream of that excel file). As per resources available on internet, browser should automatically download the file, but that's not happening.
Why downloading is not happening in browser? What's more I need to do to make it work?
NOTE : This is just for POC purpose. In actual time, I have to generate the excel file from database details, through Apache POI or some other APIs.
The below works for me:
#RequestMapping("/")
public void index(HttpServletRequest request, HttpServletResponse response) throws IOException {
FileInputStream inputStream = new FileInputStream(new File("C:\\work\\boot\\pom.xml"));
response.setHeader("Content-Disposition", "attachment; filename=\"testExcel.xlsx\"");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.copy(inputStream, outputStream);
outputStream.close();
inputStream.close();
}
What worked in my case was to make server send the following header:
Access-Control-Expose-Headers: Content-Disposition
So my problem had to do with CSRF issue.
Change the code like this:
public HttpEntity<byte[]> testMethod(#RequestParam("test") String test) {
File file = new File("C:\\testExcel.xlsx");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] array = IOUtils.toByteArray(fileInputStream);
HttpHeaders header = new HttpHeaders();
header.set("Content-type","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header.set("Content-Disposition", "attachment; filename=" + nameyouwantsaveyourfile + ".xlsx");
header.setContentLength(array.length);
fileInputStream.close();
return new HttpEntity<byte[]>(array, header);
}
I am using PrimeFaces 5.1 and JSF 2.2
Following is my code: I am generating PDF file from TableModelDate method all works fine. But it is opening in my browser How can i download it without opening.
public void PDF() throws JRException, IOException {
HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
simpleReport();
httpServletResponse.addHeader("Content-disposition", "filename=report.pdf");
ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint,servletOutputStream);
FacesContext.getCurrentInstance().responseComplete();
}
public void simpleReport() {
TableModelData();
try {
String reportPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/reports/");
JasperCompileManager.compileReportToFile(reportPath+"/Report.jrxml");
jasperPrint = JasperFillManager.fillReport(reportPath+"/Report.jasper", new HashMap(),new JRTableModelDataSource(tableModel));
} catch (JRException ex) {
ex.printStackTrace();
}
}
You are very close to it.
just add attachment; statement with the filename=xx.pdf
Like:
httpServletResponse.addHeader("Content-disposition", "attachment; filename=report.pdf");
It tells Http Servlet Responce that the file contains is attachment;
Extra:
Whenever browser opens PDF format it also shows saving option you can also save it after opening(loading) in browser
I am using poi.jar to generate excel sheet. Sometimes it does not generate the excel sheet and displays special characters in the browser.
When I generate 13 rows then it generates the excel file. But anything more than 13 rows does not generate the file.
Please help.
I am using spring following controller method to generate excel sheet.
#RequestMapping(value={"/downloadExcel"},method=RequestMethod.GET)
/*public void downloadExcel(#RequestParam(value="excelData", required=true) String excelData,
HttpServletResponse response,HttpServletRequest request) { */
public void downloadExcel(
HttpServletResponse response,HttpServletRequest request) {
Workbook wb=(Workbook)request.getSession().getAttribute("excelData");
try {
wb.write(response.getOutputStream());
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\"" + "myexcl.xls" + "\"");
}catch(IOException e)
{
Log.error("error building excel sheet "+e.getMessage()) ;
}
}
Currently my project uses a Controller class and utilizes AbstractJExcelView Class to generate an Excel Report which gives a prompt to user to either open or save the excel file. Basicall it uses http protocol for calling the controller.
Now what I need to do is generate the same excel file during (Spring) batch jobs and send it as an attachment directly through email. We're using org.springframework.mail.MailSender for sending mails.
I'm not supposed to use any other external API and I have no clue where to start from.
This is a similar code of what we're doing :-
Controller
public class RevenueReportController extends AbstractController{
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String output =
ServletRequestUtils.getStringParameter(request, "output");
//dummy data
Map<String,String> revenueData = new HashMap<String,String>();
revenueData.put("Jan-2010", "$100,000,000");
revenueData.put("Feb-2010", "$110,000,000");
revenueData.put("Mar-2010", "$130,000,000");
revenueData.put("Apr-2010", "$140,000,000");
revenueData.put("May-2010", "$200,000,000");
if(output ==null || "".equals(output)){
//return normal view
return new ModelAndView("RevenueSummary","revenueData",revenueData);
}else if("EXCEL".equals(output.toUpperCase())){
//return excel view
return new ModelAndView("ExcelRevenueSummary","revenueData",revenueData);
}else{
//return normal view
return new ModelAndView("RevenueSummary","revenueData",revenueData);
}
}
View
public class ExcelRevenueReportView extends AbstractJExcelView{
#Override
protected void buildExcelDocument(Map model, WritableWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Map<String,String> revenueData = (Map<String,String>) model.get("revenueData");
WritableSheet sheet = workbook.createSheet("Revenue Report", 0);
sheet.addCell(new Label(0, 0, "Month"));
sheet.addCell(new Label(1, 0, "Revenue"));
int rowNum = 1;
for (Map.Entry<String, String> entry : revenueData.entrySet()) {
//create the row data
sheet.addCell(new Label(0, rowNum, entry.getKey()));
sheet.addCell(new Label(1, rowNum, entry.getValue()));
rowNum++;
}
}
}
Is there any way to do that ? I need to generate the excel sheet with passed and failed job data. I can handle populating and creating the file but I have no idea how to generate the excel in buffer or may be in some temp directory which could again be attached while sending the mail. The user is not required to respond to any prompts. Neither are we going to use any http request.
Thanks in advance!
There is an MimeMessageItemWriter in Spring Batch that you should be able to use to send the emails. You'll need to create an ItemProcessor that creates the MimeMessage. You can either create the Excel file and add it as an attachment within that ItemProcessor, or have one step generate all the Excel files that need to be sent, then in the next step, you can send them. I have an example of sending emails from Spring Batch in my book: Pro Spring Batch
I did the following in and it served the purpose :-
private ByteArrayOutputStream outputStream;
outputStream = new ByteArrayOutputStream();
WritableWorkbook workbook = Workbook.createWorkbook(outputStream);
.
.
.
.
workbook.write();
workbook.close();
Now, a getter to fetch the value :-
public ByteArrayOutputStream getOutputStream()
{
return this.outputStream;
}
And finally, for email attachement :-
JavaMailSenderImpl sender = new JavaMailSenderImpl();
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(destiny);
helper.setSubject(subject);
helper.setText(msg);
helper.setFrom(from);
.
.
.
FileSystemResource fsr = new FileSystemResource(file);
helper.addAttachment("Sample.xls", fsr);
Thanks for the help guyz!
I'm using Wicket (not sure if it matters) but I'm using Workbook to create an excel file for a user to download. But I'm not sure how exactly to do this. What I would like to happen is the user clicks the button, a log is created and a prompt is given to the user to open (and save to temp files) or to save to their computer. The file is then deleted from the server side, or maybe it is stored in the User's session and deleted at end of session.
Can someone point me in the right direction? If I can have the file not saved in the session at all, that'd be create and have it just have it sent to the client using FileOutputStream somehow..
here is my current code:
private void excelCreator()
{
Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("SSA User ID " + currentSSAIDSelection2.getSsaUserId()));
Iterator<AuditLogEntry> auditLogEntrys = logList.iterator();
int i = 0;
while (auditLogEntrys.hasNext())
{
final AuditLogEntry auditLogEntry = auditLogEntrys.next();
Row row = sheet.createRow(i);
row.createCell(0).setCellValue(auditLogEntry.getTimeStamp());
row.createCell(1).setCellValue(auditLogEntry.getSourceName());
row.createCell(2).setCellValue(auditLogEntry.getCategory());
row.createCell(3).setCellValue(auditLogEntry.getSsaAdmin());
row.createCell(4).setCellValue(auditLogEntry.getAction());
i++;
}
try
{
FileOutputStream output = new FileOutputStream("ssaUserIDAccess.xls");
workbook.write(output);
output.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
You would have to create a DownloadLink with the temporary file as input. The temporary File must be deleted after download (file.delete())).
Alternatively you can try this:
IResourceStream stream = new ByteArrayResourceStream(data, "application/vnd.ms-excel");
RequestCycle.get().scheduleRequestHandlerAfterCurrent(new ResourceStreamRequestHandler(stream, filename).setContentDisposition(ContentDisposition.ATTACHMENT));
In this case data is the byte[] content of your workbook which can be for example retrieved with output.toByteArray().
In case anyone runs into this problem here is my solution. There wasn't a lot of straight forward answers on this but this is my solution:
My excelCreator method handles the creation of the excel Sheet, and returns it as a file.
private File excelCreator()
{
Workbook workbook = new HSSFWorkbook();
File excelfile = new File("userIDAccess.xls");
logList = getServer().findAuditLogs(getUserId(), null);
Sheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("User ID " + getUserId()));
Iterator<AuditLogEntry> auditLogEntrys = logList.iterator();
int i = 0;
while (auditLogEntrys.hasNext())
{
final AuditLogEntry auditLogEntry = auditLogEntrys.next();
Row row = sheet.createRow(i);
row.createCell(0).setCellValue(auditLogEntry.getTimeStamp());
row.createCell(1).setCellValue(auditLogEntry.getSourceName());
row.createCell(2).setCellValue(auditLogEntry.getCategory());
row.createCell(3).setCellValue(auditLogEntry.getSsaAdmin());
row.createCell(4).setCellValue(auditLogEntry.getAction());
i++;
}
try
{
FileOutputStream output = new FileOutputStream(excelfile);
workbook.write(output);
output.close();
}catch(Exception e)
{
e.printStackTrace();
}
return excelfile;
}
IModel excelFileModel = new AbstractReadOnlyModel()
{
public Object getObject()
{
return excelCreator();
}
};
I created an IModel to capture the file created inside my excelCreator() method and returned.
auditDownloadlink = new DownloadLink("auditDownloadlink", excelFileModel);
I pass the I.D. of the download link, and then pass the imodel.
finally,
I call,
auditDownloadlink.setDeleteAfterDownload(true);
auditDownloadlink.setCacheDuration(Duration.NONE);
This deletes the file after it is created. And the cache setting is a setting to make sure it is compatible with all browsers (That's how I interpreted it, but you may not need it).
The Imodel creates the File on the fly so it doesn't have to be stored anywhere, and then the file is deleted once it is downloaded.
Hope this helps someone!
You could create a Resource to do this, and make a ResourceLink.
public class ExcelProducerResource extends AbstractResource
{
public ExcelProducerResource()
{
}
#Override
protected ResourceResponse newResourceResponse( Attributes attributes )
{
final String fileName = getFileName();
ResourceResponse resourceResponse = new ResourceResponse();
resourceResponse.setContentType( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" );
resourceResponse.setCacheDuration( Duration.NONE );
resourceResponse.setFileName( fileName );
resourceResponse.setWriteCallback( new WriteCallback()
{
#Override
public void writeData( Attributes attributes ) throws IOException
{
OutputStream outputStream = attributes.getResponse().getOutputStream();
writeToStream( outputStream );
outputStream.close();
}
} );
return resourceResponse;
}
void writeToStream(OutputStream outputStream) throws IOException
{
//.. do stuff here :)
}
String getFileName()
{
//.. do stuff here :)
}
}