I am developing an application in GWT, I am using the api to generate JasperReports reports, initially tried to make the generation via RPC, which returned to the client a string with the path of the pdf created, but that did not work, now I'm trying to generate report by a normal servlet, but the report is generated, nothing appears on the screen, and no error is found in the browser console.
Details:
dev mode works perfectly.
on localhost: 8080 works perfectly.
The error is when the application is published in an external Tomcat
Here are my code
Servlet:
public class RelatorioPacienteServiceImpl extends HttpServlet {
private static final long serialVersionUID = 1L;
private ServletContext sc;
public void init(ServletConfig config) throws ServletException {
super.init(config);
sc = config.getServletContext();
}
#SuppressWarnings({ "unused", "unchecked", "rawtypes" })
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id = req.getParameter("id");
Map m = req.getParameterMap();
Paciente paciente = new Paciente();
File reportFile = null;
String dir = sc.getRealPath(sc.getContextPath().replaceAll("\\\\", "/"));
Map parameters = new LinkedHashMap();
String path = dir + "/../reports/";// tomcat
path = path.replaceAll("\\\\", "/");
try {
paciente = PacienteDAO.getPacientePorId(Integer.parseInt(id));
List<Paciente> list = new ArrayList<>();
list.add(paciente);
HashMap parametros = new HashMap<String, Boolean>();
parametros.put("cpf", NumberMask.formatCpf(paciente.getCpf()));
parametros.put("telefone1",NumberMask.formatPhone(paciente.getTelefone1()));
parametros.put("telefone2",NumberMask.formatPhone(paciente.getTelefone2()));
parametros.put("telefoneResponsavel",NumberMask.formatPhone(paciente.getTelefoneResponsavel()));
parametros.put("dataNascimento",StringUtil.formatDate(paciente.getDataNascimento()));
switch (paciente.getEtnia()) {
case EtniaProps.BRANCA:
parametros.put("etnia","Branco");
break;
case EtniaProps.INDIGENA:
parametros.put("etnia","Indigena");
break;
case EtniaProps.PARDA:
parametros.put("etnia","Parda");
break;
case EtniaProps.PRETA:
parametros.put("etnia","Preta");
break;
default:
break;
}
reportFile = new File(path + "report_paciente.jasper");
byte[] bytes = null;
JRDataSource jrds = new JRBeanCollectionDataSource(list);
try {
bytes = JasperRunManager.runReportToPdf(reportFile.getPath(), parametros, jrds);
} catch (JRException ex) {
ex.printStackTrace();
System.out.println("Erro ao gerar o relatório " + ex.getMessage());
}
if (!list.isEmpty()) {
if (bytes != null && bytes.length > 0) {
resp.setContentType("application/pdf");
resp.setContentLength(bytes.length);
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write(bytes, 0, bytes.length);
outputStream.flush();
outputStream.close();
}
} else {
resp.setContentType("text/html");
ServletOutputStream outputStream = resp.getOutputStream();
String mensagem = "<html>" + "<head>" + "<meta http-equiv=\"content-type\" charset=\"UTF-8\" content=\"text/html\">"
+ "<title>Incor lages</title>" + "</head>" + "<body>"
+ "<br><br><br><br><h1>Documento sem paginas" + "</body>" + "</html>";
outputStream.write(mensagem.getBytes(), 0, mensagem.getBytes().length);
resp.setContentLength(mensagem.getBytes().length);
outputStream.flush();
outputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Erro ao execura a query " + e.getMessage());
}
}
Calling servlet:
String url = GWT.getModuleBaseURL() + "relatorioPacienteService?id=" + paciente.getId();
Window.open(url, "_blank", "");
Any help would be appreciated
Can u print reportFile.getPath(). I doubt the path of .jasper file is incorrect.
First of all it would be even better If you can post your .jrxml file.
Based on the info available (report is generated, but blank), I think following is the area of concern:
paciente = PacienteDAO.getPacientePorId(Integer.parseInt(id));
List<Paciente> list = new ArrayList<>();
list.add(paciente);
Make sure PacienteDAO.getPacientePorId(Integer.parseInt(id)); is actually returning a bean. Beacuse If it does not return anything or returns null, the data source you use i.e. JRBeanCollectionDataSource, will have no data and hence nothing would be displayed.
Related
A web application prints PDF reports without problems, but when reports in xlsx, docx, csv, rtf, etc. are all not configured correctly. The browser tries to save the file always with the .xhtml extension.
How do you export the report to a browser such that the file exports with the correct filename and media type?
Code:
public void gerarJasper(String name, String type, List data, Map params) throws IllegalArgumentException, RuntimeException, Exception {
boolean found = false;
for (int i = 0; i < VALID_TYPES.length; i++) {
if (VALID_TYPES[i].equals(type)) {
found = true;
break;
}
}
if (!found) {
throw new IllegalArgumentException("Tipo solicitado '" + type + "' inválido");
}
// Procurar recurso de design de relatório compilado
ExternalContext econtext = FacesContext.getCurrentInstance().getExternalContext();
InputStream stream = econtext.getResourceAsStream(PREFIX + name + SUFFIX);
if (stream == null) {
throw new IllegalArgumentException("O relatório '" + name + "' não existe");
}
FacesContext fc = FacesContext.getCurrentInstance();
ServletContext context = (ServletContext)fc.getExternalContext().getContext();
String path = context.getRealPath(File.separator) + "resources/jasper" + File.separator;
String logo = context.getRealPath(File.separator) + "resources/imagens" + File.separator;
params.put("SUBREPORT_DIR", path);
params.put("LOGO_DIR", logo);
JRDataSource ds = new JRBeanArrayDataSource(data.toArray());
JasperPrint jasperPrint = null;
try {
jasperPrint = JasperFillManager.fillReport(stream, params, ds);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
} finally {
try {
stream.close();
} catch (IOException e) {
}
}
JRExporter exporter = null;
HttpServletResponse response = (HttpServletResponse) econtext.getResponse();
FacesContext fcontext = FacesContext.getCurrentInstance();
try {
response.setContentType(type);
if ("application/pdf".equals(type)) {
exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
} else if ("text/html".equals(type)) {
exporter = new JRHtmlExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, response.getWriter());
// Tornar imagens disponÃveis para a saÃda HTML
HttpServletRequest request = (HttpServletRequest) fcontext.getExternalContext().getRequest();
request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, new HashMap());
// A seguinte instrução requer mapeamento / imagem
// para o imageServlet no web.xml.
//
// Este servlet serve imagens, incluindo imagens px
// para espaçamento.
//
// Sirva as imagens diretamente para não
// incorrermos em tempo extra associado a
// a uma solicitação JSF para uma entidade não-JSF.
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + "/image?image=");
}else if("application/xlsx".equals(type)){
exporter = new JRXlsxExporter();
exporter.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, response.getOutputStream());
//exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS,new Boolean(true));
exporter.setParameter(JRXlsExporterParameter.OUTPUT_FILE, name+".xlsx");
exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
exporter.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
}else if("application/csv".equals(type)){
exporter = new JRCsvExporter();
exporter.setParameter(JRCsvExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRCsvExporterParameter.OUTPUT_STREAM, response.getOutputStream());
exporter.setParameter(JRCsvExporterParameter.OUTPUT_FILE_NAME, name+".csv");
}else if("application/docx".equals(type)){
exporter = new JRDocxExporter();
exporter.setParameter(JRDocxExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRDocxExporterParameter.OUTPUT_STREAM, response.getOutputStream());
} else if("application/rtf".equals(type)){
exporter = new JRRtfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
try {
exporter.exportReport();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
fcontext.responseComplete();
}
Summary
The "Content-Disposition" HTTP response header is not being set. Set it using:
response.setHeader(
"Content-Disposition",
"attachment; filename=".concat(name).concat(filenameExtension)
);
But this is not the only problem.
Servlet vs. JSF Page
Although the question does not include how the report is being called, I'm going to assume it's one of:
Download
Download
This will lead to troubles (such as exceptions due to the output stream being closed twice). Use a Servlet, instead, to generate a report for download. The link will become:
Download
See also:
https://github.com/deadlydirk/jasperreports-example/blob/master/src/main/java/be/example/jasper/servlet/ReportServlet.java
https://stackoverflow.com/a/35698286/59087
Don't use FacesContext to get the HTTP response stream. Use a Servlet, instead, and implement the doGet and doPost methods.
Code Simplifications
The following code:
boolean found = false;
for (int i = 0; i < VALID_TYPES.length; i++) {
if (VALID_TYPES[i].equals(type)) {
found = true;
break;
}
}
if (!found) {
throw new IllegalArgumentException("Tipo solicitado '" + type + "' inválido");
}
Reduces to:
if( !Arrays.asList(VALID_TYPES).contains(type) ) {
throw new IllegalArgumentException("Tipo solicitado '" + type + "' inválido");
}
Create a ReportFormat enumeration that associates a file extension with its application type in a robust, reusable way:
public enum ReportFormat {
/**
* Adobe Acrobat Portable Document Format.
*
* #see https://tools.ietf.org/html/rfc3778
*/
PDF("application/pdf", "pdf"),
/**
* Hypertext Mark-up Language.
*
* #see https://www.ietf.org/rfc/rfc2854.txt
*/
HTML("text/html", "html"),
/**
* Comma-separated Values.
*
* #see https://tools.ietf.org/html/rfc4180
*/
CSV("text/csv", "csv"),
/**
* Proprietary Microsoft Excel Format (see also: CSV).
*
* #see http://www.iana.org/assignments/media-types/application/vnd.ms-excel
*/
XLS("application/vnd.ms-excel", "xls"),
/**
* The media type as defined by IANA and IETF.
*
* #see http://www.iana.org/assignments/media-types/media-types.xhtml
*/
private final String mediaType;
/**
* The filename extension typically used for this format's media type.
*/
private final String extension;
private ReportFormat(
final String mediaType,
final String extension) {
this.mediaType = mediaType;
this.extension = extension;
}
public String getFilenameExtension() {
return this.extension;
}
/**
* Returns the media type (formerly MIME type) for this report format
* suitable for inclusion in the content-header of an HTTP response.
*
* #return The report format media type.
* #see http://www.iana.org/assignments/media-types/media-types.xhtml
*/
public String getMediaType() {
return this.mediaType;
}
}
Now, instead of passing in the type, you can write:
public void gerarJasper(String name, ReportFormat reportFormat, ... ) {
}
Then there's no need to check for the report format because only known types can be passed. This further reduces the code to:
if( reportFormat == null ) {
throw new IllegalArgumentException("Tipo solicitado null inválido");
}
Alternatively, assume a default format and the method will throw one few error conditions to handle:
if( reportFormat == null ) {
// Returns ReportFormat.PDF by default.
reportFormat = getDefaultFormat();
}
Next, the following code:
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
Reduces to:
} catch (Exception e) {
throw new FacesException(e);
}
There are a number of other simplifications that can be made. See the Command Pattern for details. For example:
FacesContext fc = FacesContext.getCurrentInstance();
FacesContext fcontext = FacesContext.getCurrentInstance();
Only one FacesContext instance is necessary, so you can delete fcontext (or fc).
As for the problem, the content disposition is not set via the HTTP response. With ReportFormat in place, create some new methods:
private void setHeader(final String name, final String value) {
getResponse().setHeader(name, value);
}
private HttpServletResponse getResponse() {
final ExternalContext ctx = getFacesContext().getExternalContext();
final HttpServletResponse response = (HttpServletResponse) ctx.getResponse();
return response;
}
Next, introduce a constant and additional methods:
private static final String CONTENT_DISPOSITION = "Content-Disposition";
protected void setContentType(final String mediaType) {
getResponse().setContentType(mediaType);
}
protected void setContentDisposition(final String filename) {
setHeader(CONTENT_DISPOSITION, "attachment; filename=".concat(filename));
}
Call them like:
setContentType( reportFormat.getMediaType() );
setContentDisposition( name + "." + reportFormat.getFilenameExtension() );
The code shown in the question is overly complex. Applying some common design patterns will make it easier to maintain.
I trying to load jasper report (.jrxml) that i created, i named the report "JREmp1.xml". but i got this error
"HTTP Status 500 - Request processing failed; nested exception is
net.sf.jasperreports.engine.JRException:
java.io.FileNotFoundException:
D:\printpdf.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JasperExample\jasper\JREmp1.jrxml
(The system cannot find the path specified)"
how to got the exact location? here is my JREmp1.xml file location :
and here is code in my controller class :
#RequestMapping(value = "/generateReport", method = RequestMethod.POST)
public String generateReport(
#Valid #ModelAttribute("jasperInputForm") JasperInputForm jasperInputForm,
BindingResult result, Model model, HttpServletRequest request,
HttpServletResponse response) throws JRException, IOException,
NamingException {
if (result.hasErrors()) {
System.out.println("validation error occured in jasper input form");
return "loadJasper";
}
String reportFileName = "JREmp1";
JasperReportDAO jrdao = new JasperReportDAO();
Connection conn = null;
try {
conn = jrdao.getConnection();
String rptFormat = jasperInputForm.getRptFmt();
String noy = jasperInputForm.getNoofYears();
System.out.println("rpt format " + rptFormat);
System.out.println("no of years " + noy);
HashMap<String, Object> hmParams = new HashMap<String, Object>();
hmParams.put("noy", new Integer(noy));
hmParams.put("Title", "Employees working more than " + noy
+ " Years");
JasperReport jasperReport = jrdao.getCompiledFile(reportFileName,
request);
if (rptFormat.equalsIgnoreCase("html")) {
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport, hmParams, conn);
jrdao.generateReportHtml(jasperPrint, request, response); // For
// HTML
// report
}
else if (rptFormat.equalsIgnoreCase("pdf")) {
jrdao.generateReportPDF(response, hmParams, jasperReport, conn); // For
// PDF
// report
}
} catch (SQLException sqlExp) {
System.out.println("Exception::" + sqlExp.toString());
} finally {
if (conn != null) {
try {
conn.close();
conn = null;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
Here is the code in my JasperReportDAO class :
public JasperReport getCompiledFile(String fileName, HttpServletRequest request) throws JRException {
System.out.println("path " + request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jasper"));
File reportFile = new File( request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jasper"));
// If compiled file is not found, then compile XML template
if (!reportFile.exists()) {
JasperCompileManager.compileReportToFile(request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jrxml"),request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jasper"));
}
JasperReport jasperReport = (JasperReport) JRLoader.loadObjectFromFile(reportFile.getPath());
return jasperReport;
}
public void generateReportHtml( JasperPrint jasperPrint, HttpServletRequest req, HttpServletResponse resp) throws IOException, JRException {
HtmlExporter exporter=new HtmlExporter();
List<JasperPrint> jasperPrintList = new ArrayList<JasperPrint>();
jasperPrintList.add(jasperPrint);
exporter.setExporterInput(SimpleExporterInput.getInstance(jasperPrintList));
exporter.setExporterOutput( new SimpleHtmlExporterOutput(resp.getWriter()));
SimpleHtmlReportConfiguration configuration =new SimpleHtmlReportConfiguration();
exporter.setConfiguration(configuration);
exporter.exportReport();
}
public void generateReportPDF (HttpServletResponse resp, Map parameters, JasperReport jasperReport, Connection conn)throws JRException, NamingException, SQLException, IOException {
byte[] bytes = null;
bytes = JasperRunManager.runReportToPdf(jasperReport,parameters,conn);
resp.reset();
resp.resetBuffer();
resp.setContentType("application/pdf");
resp.setContentLength(bytes.length);
ServletOutputStream ouputStream = resp.getOutputStream();
ouputStream.write(bytes, 0, bytes.length);
ouputStream.flush();
ouputStream.close();
}
and here is my JasperInputForm class :
public class JasperInputForm {
#NotEmpty
private String noofYears;
private String rptFmt="Html";
public String getRptFmt() {
return rptFmt;
}
public void setRptFmt(String rptFmt) {
this.rptFmt = rptFmt;
}
public String getNoofYears() {
return noofYears;
}
public void setNoofYears(String noofYears) {
this.noofYears = noofYears;
}
}
how to get my JREmp1.jrxml file location properly? I develop this report for Spring MVC application
UPDATE :
Here is my complete function code after i update with #Wilson answer (i go with second option that #Wilson said) :
this function is inside JasperReportDAO :
public JasperReport getCompiledFile(String fileName, HttpServletRequest request) throws JRException, MalformedURLException, URISyntaxException {
System.out.println("path " + request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jasper"));
//File reportFile = new File( request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jasper"));
URL resourceUrl = request.getSession().getServletContext().getResource("/WEB-INF/jasper/" + fileName + ".jrxml");
File reportFile = new File(resourceUrl.toURI());
// If compiled file is not found, then compile XML template
if (!reportFile.exists()) {
JasperCompileManager.compileReportToFile(request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jrxml"),request.getSession().getServletContext().getRealPath("/jasper/" + fileName + ".jasper"));
}
JasperReport jasperReport = (JasperReport) JRLoader.loadObjectFromFile(reportFile.getPath());
return jasperReport;
}
and i got this error
"HTTP Status 500 - Request processing failed; nested exception is
java.lang.IllegalArgumentException: URI scheme is not "file""
How to solve this?
There is a number of way to do to read file with ServeltContext:
1.
Use ServletContext#getRealPath
String fullPath = request.getSession().getServletContext().getRealPath("/WEB-INF/jasper/" + fileName + ".jrxml");
This will get you the full system path to the resource you are looking for. However, it will not work if the container do not expand the WAR file.
2.
Use ServletContext#getResource
URL resourceUrl = request.getSession().getServletContext().getResource("/WEB-INF/jasper/" + fileName + ".jrxml");
File file = new File(resourceUrl.toURI());
This will return the URL no matter what container you use and where the application is installed.
3.
User ServletContext#getResourceAsStream
InputStream resourceStream = request.getSession().getServletContext().getResourceAsStream("/WEB-INF/jasper/" + fileName + ".jrxml");
This is an alternative of ServletContext#getResource to get an inputSteam
UPDATE:
The URL return from ServletContext#getResource may not be a file URL and it may cause issue. Please try ServletContext#getResourceAsStream with JasperCompileManager#compileReportToFile:
JasperDesign jasperDesign = JRXmlLoader.load(resourceStream);
JasperCompileManager.compileReportToFile(jasperDesign, jasperFilePath);
I found that your are trying to write jasper report file into your program distribution which should be avoid. The preferred way is to pre-compile your report and put into your WAR file or put the compiled jasper report into a temporary directory.
Following is full code example:
public JasperReport getCompiledFile(String fileName, HttpServletRequest request) throws JRException, IOException {
// Create temporary folder to store jasper report as you should not write a resource into your program
// distribution
String tempFolderPath = System.getProperty("java.io.tmpdir") + File.separator + "jasperReport";
File tempFolder = new File(tempFolderPath);
if (!tempFolder.exists()) {
tempFolder.mkdirs();
}
String jasperFilePath = tempFolderPath + File.separator + fileName + ".jasper";
File reportFile = new File(jasperFilePath);
// If compiled file is not found, then compile XML template
if (!reportFile.exists()) {
InputStream jRXmlStream = request.getSession().getServletContext().getResourceAsStream
("/WEB-INF/jasper/" + fileName + ".jrxml");
JasperDesign jasperDesign = JRXmlLoader.load(jRXmlStream);
JasperCompileManager.compileReportToFile(jasperDesign, jasperFilePath);
}
JasperReport jasperReport = (JasperReport) JRLoader.loadObjectFromFile(reportFile.getPath());
return jasperReport;
}
We can use the below code snippet if the jrxml is present in Resource folder -
InputStream employeeReportStream = getClass().getResourceAsStream("/report.jrxml");
JasperReport report = JasperCompileManager.compileReport(employeeReportStream);
I got a problem when files were download , I can't get any actions or events when clicking any links , butttons and menues after download process was done.
Below is my codes for excel file download button ...
Button btnDownloadExcel = new Button("Excel Download");
btnDownloadExcel.addStyleName("downloadButton");
btnDownloadExcel.addClickListener(new ClickListener() {
#Override
public void buttonClick(final ClickEvent event) {
StringBuilder url = new StringBuilder("/myproject/filedownload.html?category=excel");
url.append("&seq=" + 111);
getUI().getPage().open(url.toString(), "_self");
}
});
Below is servlet for handle excel file download request (I used JExcel API for excel file)
#WebServlet(value = "/filedownload.html")
public class DownloadServletController extends HttpServlet {
private final Logger log = LoggerFactory.getLogger(DownloadServletController.class);
protected final void doGet(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException, IOException {
String category = request.getParameter("category");
long seq = request.getParameter("seq") == null ? -1L : Long.parseLong(request.getParameter("seq"));
byte[] stream = null;
if (category.equals("excel")) {
try {
stream = getSampleExcelStream(seq);
}
catch (BusinessException e) {
log.error("Generating streams for " + category + " got Error !" + e);
}
ExcelSupport.createExcel("Test", seq, stream, response);
}
}
private byte[] getSampleExcelStream(final long seq) throws BusinessException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
String staticDir = System.getProperty("staticDir");
String templateDir = staticDir + "/templates/sample_excel_template.xls";
WorkbookSettings wsWrite = new WorkbookSettings();
wsWrite.setEncoding("UTF-8");
wsWrite.setAutoFilterDisabled(false);
WritableWorkbook workBook = Workbook.createWorkbook(baos, Workbook.getWorkbook(new File(templateDir)),
wsWrite);
workBook.write();
baos.close();
workBook.close();
}
catch (BiffException e) {
throw new BusinessException("Excel file Creating Error!");
}
catch (WriteException e) {
throw new BusinessException("Error ! writing excel file process has occured!");
}
catch (FileNotFoundException e) {
throw new BusinessException("FileNotFoundException, when getting stream for excel", e);
}
catch (IOException e) {
throw new BusinessException("IOException, when getting stream for excel", e);
}
return baos.toByteArray();
}
}
ExcelSupport.java is below
public final class ExcelSupport {
private ExcelSupport() {
}
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelSupport.class);
public static void createExcel(final String fileNamePrefix, final long seq,
final byte[] stream, final HttpServletResponse response) {
StringBuffer fileName = new StringBuffer();
fileName.append(fileNamePrefix + "_");
if (seq > -1) {
fileName.append("(uid-" + seq + ")_");
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
fileName.append(sdf.format(new Date()));
fileName.append(".xls");
StringBuffer sbContentDispValue = new StringBuffer();
sbContentDispValue.append("inline");
sbContentDispValue.append("; filename=");
sbContentDispValue.append(fileName);
response.setContentType("application/msexcel");
response.addHeader("Cache-Control", "max-age=30");
response.addHeader("Content-disposition", sbContentDispValue.toString());
response.setContentLength(stream.length);
try {
ServletOutputStream osStream = response.getOutputStream();
osStream.write(stream);
osStream.flush();
osStream.close();
}
catch (IOException e) {
LOGGER.error("Creating Excel for " + fileName + " got Error !" + e);
}
}
}
Can somebody correct me what I am wrong ? Download process was fine , nothing error and I got excel file successfully. But I have no idea why browser was freeze. I can't see any error logs or messages in IDE console and browser's console. Thanks for reading my question !
PS : I am sure this codes work fine and did not freeze on other GWT projects.
Now I found the problem . I used Network console of Firefox 31 and here is screen-shoot for before download and here is after download. I notice that I lost all web datas because the replacing url by getUI().getPage().open(url.toString(), "_self");
So , if I use others instead of _self , everythings were fine but browsers were block popups. I can't tell the users to enable popups of their browsers . So , finally I use Link component as below ..
Link linkDownloadExcel = new Link("Excel Download", new ExternalResource(
"/myproject/filedownload.html?category=excel&seq=" + 111), "_blank", -1, -1, BorderStyle.DEFAULT);
linkDownloadExcel.addStyleName("downloadButton");
linkDownloadExcel.setIcon(new ExternalResource("/myproject/images/excel-icon.png"));
hlButtonLayout.addComponent(linkDownloadExcel);
I have this servlet to handle uploaded file and to store them on server.
public class ImageService extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final long MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB
#Override
protected void doPost(final HttpServletRequest request,
final HttpServletResponse response) {
slog("SERVLET STARTED");
List<String> files = new ArrayList<String>();
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
slog("REQUEST IS MULTIPART");
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/html");
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(MAX_FILE_SIZE);
try {
List<FileItem> items = upload.parseRequest(request);
Iterator<FileItem> iterator = items.iterator();
while (iterator.hasNext()) {
FileItem item = iterator.next();
if (!item.isFormField()) {
String fileName = item.getName();
slog("TROVATO FILE " + item.getName());
String root = getServletContext().getRealPath("/");
File path = new File(root + "/fileuploads");
slog("SALVO FILE IN " + path.getAbsolutePath());
if (!path.exists()) {
path.mkdirs();
}
File uploadedFile = creaFileNonAmbiguo(path, fileName);
slog("NOME ASSEGNATO AL FILE " + uploadedFile.getName());
item.write(uploadedFile);
response.getWriter()
.write(uploadedFile.getName() + ";");
files.add(uploadedFile.getName());
}
}
response.getWriter().flush();
slog("RISPOSTA INVIATA");
} catch (Exception e) {
e.printStackTrace();
}
} else {
slog("LA RICHIESTA NON E' MULTIPART");
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
slog("SERVLET TERMINATA");
}
#Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response) {
response.setContentType("image/jpeg");
String root = getServletContext().getRealPath("/").concat(
"fileuploads/");
String path = root.concat(request.getParameter("src"));
File file = new File(path);
response.setContentLength((int) file.length());
FileInputStream in;
try {
in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) >= 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private File creaFileNonAmbiguo(File path, String fileName) {
File res = new File(path + "/" + fileName);
if (!res.exists())
return res;
else {
return creaFileNonAmbiguo(path, "c".concat(fileName));
}
}
private void slog(String s) {
System.out.println("UPLOAD SERVLET: " + s);
}
}
As you can see the servlet has doPost and doGet. doGet() is correctly called in this part of my code:
[...]
String path = GWT.getModuleBaseURL() + "imageUpload?src=";
for (String foto : result) {
String url = path.concat(foto);
[...]
But the doPost method is never called, as I can see from the Chrome debugger and from the fact that SERVLET STARTED is never logged.
This is the way I call the doPost() method from client:
inserisciSegnalazioneBtn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
if (!catLst.isEnabled()
|| catLst.getItemText(catLst.getSelectedIndex())
.equals("")
|| catLst.getItemText(catLst.getSelectedIndex())
.equals("")
|| descrizioneBox.getText().equals("")
|| gsb.getText().equals("")) {
Window.alert("ATTENZIONE: devi riempire tutti i campi");
return;
}
segnalazione.setCategoria(new Categoria(catLst.getItemText(catLst
.getSelectedIndex())));
segnalazione.setDescrizione(descrizioneBox.getText());
segnalazione.setIndirizzo(gsb.getText());
segnalazione.setUtente(LoginPanel.username);
Segnalazioni_Degrado.dataLayerService.inserisciSegnalazione(
segnalazione, new AsyncCallback<Boolean>() {
#Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
#Override
public void onSuccess(Boolean result) {
if (result) {
geocode(segnalazione);
uploadFrm.submit();
Window.alert("Inserimento avvenuto con successo");
MenuPanel.refreshBtn.click();
} else
Window.alert("L'inserimento ha avuto esito negativo");
thisPnl.hide();
}
});
}
});
uploadFrm.setAction(GWT.getModuleBaseURL() + "imageUpload");
uploadFrm.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadFrm.setMethod(FormPanel.METHOD_POST);
uploadFrm
.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
Window.alert("SUBMIT COMPLETATO");
String res = event.getResults();
if (res != null && !res.equals("")) {
Window.alert("IL SERVER RISPONDE " + res.toString());
String[] uploadedFiles = res.split(";");
aggiornaFotoDB(uploadedFiles, segnalazione);
}
}
});
The weird thing is that it works properly on DevMode, but it doesn't work when I deploy my webapp to Tomcat.
What's wrong with my code?
It turned out that the problem was
thisPnl.hide();
The solution was to hide the panel INSIDE the SubmitCompleteHandler
I am using this gwt upload system here(http://code.google.com/p/gwtupload/). I am getting some problems with it.
Show to feed it with a path from the client
Get the path on the server where the file was saved
set a path on the server where the file is to be saved
This the servlet to handle the file upload
public class SampleUploadServlet extends UploadAction {
private static final long serialVersionUID = 1L;
Hashtable<String, String> receivedContentTypes = new Hashtable<String, String>();
/**
* Maintain a list with received files and their content types.
*/
Hashtable<String, File> receivedFiles = new Hashtable<String, File>();
/**
* Override executeAction to save the received files in a custom place
* and delete this items from session.
*/
#Override
public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
String response = "";
int cont = 0;
for (FileItem item : sessionFiles) {
if (false == item.isFormField()) {
cont ++;
try {
/// Create a new file based on the remote file name in the client
// String saveName = item.getName().replaceAll("[\\\\/><\\|\\s\"'{}()\\[\\]]+", "_");
// File file =new File("/tmp/" + saveName);
/// Create a temporary file placed in /tmp (only works in unix)
// File file = File.createTempFile("upload-", ".bin", new File("/tmp"));
/// Create a temporary file placed in the default system temp folder
File file = File.createTempFile("upload-", ".bin");
item.write(file);
/// Save a list with the received files
receivedFiles.put(item.getFieldName(), file);
receivedContentTypes.put(item.getFieldName(), item.getContentType());
/// Compose a xml message with the full file information which can be parsed in client side
response += "<file-" + cont + "-field>" + item.getFieldName() + "</file-" + cont + "-field>\n";
response += "<file-" + cont + "-name>" + item.getName() + "</file-" + cont + "-name>\n";
response += "<file-" + cont + "-size>" + item.getSize() + "</file-" + cont + "-size>\n";
response += "<file-" + cont + "-type>" + item.getContentType()+ "</file-" + cont + "type>\n";
} catch (Exception e) {
throw new UploadActionException(e);
}
}
}
/// Remove files from session because we have a copy of them
removeSessionFileItems(request);
/// Send information of the received files to the client.
return "<response>\n" + response + "</response>\n";
}
/**
* Get the content of an uploaded file.
*/
#Override
public void getUploadedFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
String fieldName = request.getParameter(PARAM_SHOW);
File f = receivedFiles.get(fieldName);
if (f != null) {
response.setContentType(receivedContentTypes.get(fieldName));
FileInputStream is = new FileInputStream(f);
copyFromInputStreamToOutputStream(is, response.getOutputStream());
} else {
renderXmlResponse(request, response, ERROR_ITEM_NOT_FOUND);
}
}
/**
* Remove a file when the user sends a delete request.
*/
#Override
public void removeItem(HttpServletRequest request, String fieldName) throws UploadActionException {
File file = receivedFiles.get(fieldName);
receivedFiles.remove(fieldName);
receivedContentTypes.remove(fieldName);
if (file != null) {
file.delete();
}
}
}
Thanks
Try with this:
public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
for (FileItem item : sessionFiles) {
if (false == item.isFormField()) {
String uploadedFileName = "";
try {
String uploadsDir = "/uploads";
File dirFile = new File(uploadsDir);
dirFile.mkdirs();
String filename = FilenameUtils.getName(item.getName()); // uploaded file filename
File file = new File(uploadsDir, filename);
item.write(file);
uploadedFileName = uploadsDir + "/" + filename;
} catch (Exception e) {
logger.error("ERROR UPLOADING FILE: " + uploadedFileName + ", Exception: " + e);
throw new UploadActionException(e.getMessage());
}
}
removeSessionFileItems(request);
}
return null;
}
Happy coding!
Regards.