I build a PDF document with iText library, and i want to get this document by clicking a link in the webapp.
But, it happens... nothing. No error message, no exception, really nothing.
I really don't master IO Streaming, so I think I made a mistake on this point, but after few hours of research, I don't know and I need a bit of help.
I have two methods. The first is the one to create pdf doc.
public void exporterPDF(SomeObjectIWillUse o) {
Document documentPDF = new Document(PageSize.A4);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(documentPDF, baos);
documentPDF.open();
documentPDF.addTitle("Test ! ");
Paragraph par = new Paragraph("Liste des participants");
documentPDF.add(par)
documentPDF.close();
telechargerPdfViaVue(FacesContext.getCurrentInstance(), baos, "filename.pdf");
} catch (Exception e) {
// TODO Auto-generated catch block
JsfUtils.addMessageByCode(FacesMessage.SEVERITY_FATAL, "drc.export.generation.pdf.erreur");
}
}
And the second is use to send the document.
public static final void telechargerPdfViaVue(FacesContext context, ByteArrayOutputStream baos, String fileName) throws IOException, DocumentException {
ExternalContext externalContext = context.getExternalContext();
externalContext.setResponseContentType("application/pdf");
externalContext.setResponseHeader("Expires", "0");
externalContext.setResponseHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
externalContext.setResponseHeader("Pragma", "public");
externalContext.setResponseHeader("Content-disposition", "attachment;filename=" + fileName);
externalContext.setResponseContentLength(baos.size());
OutputStream out = externalContext.getResponseOutputStream();
baos.writeTo(out);
externalContext.responseFlushBuffer();
context.responseComplete();
}
and it's called on my web page by a simple commandeLink
<p:commandLink id="exportPdf" action="#{myBean.exporterPDF(o)}">
Literally, in debug mode, all is done, but nothing happen...
Thank you for your help!
More informations, I use :
- JSF 2.2.7
- Spring 4.0.6
Related
I am trying to learn iText7(7.0.2), and building a basic pdf, but encountering an error at document.add(new Paragraph("Hello World!")), saying
The method add(AreaBreak) in the type Document is not applicable for the arguments (Paragraph)"
Any help will be thankful.
public static void main(String args[]) throws IOException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new PdfTest().createPdf(DEST);
}
public void createPdf(String dest) throws IOException {
//Initialize PDF writer
PdfWriter writer = new PdfWriter(dest);
//Initialize PDF document
PdfDocument pdf = new PdfDocument(writer);
// Initialize document
Document document = new Document(pdf);
//Add paragraph to the document
document.add(new Paragraph("Hello World!"));
//Close document
document.close();
}
Just run your example. It's work perfectly fine. My best guess is you have old caches from itextpdf5. Make sure your .pom-file contains only itext7 dependencies. And, as mkl mentioned in his comment, correct way to import Paragraph is
import com.itextpdf.layout.element.Paragraph
I can download data via HttpUrlConnection and InputStream but I need to download raw-data. So, i want to create a DownloadManager via raw-data, then using raw-data I convert this data to binary or image format. According to my research, I see "download file from url" but I can't download file in mac? Always, I get FileNotFoundException. Please help me. How I can download data from url?
public class DownloadData extends AsyncTask<Void,Void,Void> {
#Override
protected Void doInBackground(Void... params) {
try {
downloadData("https://blablalabla/get");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void downloadData(String myurl) throws IOException {
URL u = new URL(myurl);
InputStream is = u.openStream();
DataInputStream dis = new DataInputStream(is);
byte[] buffer = new byte[1024];
int length;
OutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/Users/ilknurpc/Desktop/text.docx"));
while ((length = dis.read(buffer))>0) {
fos.write(buffer, 0, length);
}
}
}
If you want to construct a workable download manager, I would suggest that you take a look at the
Tomcat Default Servlet Implementation
.
There a few number of HTTP headers that you need to understand such as E-Tags and Http Range Headers for a proper implementation.
Thankfully the Tomcat Default Servlet handles the prerequisites for you.
You can adapt this servlet in your code with minor changes (package declaration etc).
first of all I want to say that I am new in html/jsp/java/servlets, etc... and thanks to this forum i managed to get my first webapp working. But now I am having a problem and i couldnt find a solution on the site.
The problem is that I call a servlet from a jsp, this servlet deploys different applications and I simply want to show the println that I call in the servlet before de servlet ends, right now, even If I have 10 println in different moments of the deploy process, the server only shows them when the servlets ends processing, which doesnt hace much sense for my app because i am trying to show the different steps of the deploy.
The servlet code is something like this:
public class Deploys extends HttpServlet {
String HOME = System.getenv("TRACE_HOME");
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
final PrintWriter out = res.getWriter();
String broker = req.getParameter("Broker");
String eg = req.getParameter("Eg");
String servicio = req.getParameter("cboServicios");
String bar = req.getParameter("cboBarFiles");
// deploy
BrokerProxy b;
try {
out.println("connecting to server");
b = utils.connect("LOCALQM");
out.println("connect succesfull");
ExecutionGroupProxy e = b.getExecutionGroupByName(eg);
String path = HOME + "\\deploys\\files\\" + servicio + "\\";
DeployResult dr = e.deploy(path + bar,true, 60000);
out.println("Deployment completion code = "+dr.getCompletionCode());
} catch (ConfigManagerProxyLoggedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ConfigManagerProxyPropertyNotInitializedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
and the server shows this all at the same time
connecting to server
connect succesfull
starting deploy
deploy completed
I read that the way to to this is using ajax an jquetr but I couldnt find an example of how to do it, so if any one can help will be very appreciated
It's because it only does everything when the servlet is fully deployed, so it will do everything on the servlet almost instantly. At least that's how I learned it.
I think you could only do it editing the server or something like that. I don't think it's possible to do it on jQuery or ajax because the servlet would already be deployed. What you can do, however, is to do those outputs at servlet execution, so it prints while it's processing the code.
OK, I found a solution, I am not sure if its the best way to do it or if it is just a workaround, but it works!
I used flush() and the most important is that I had to set the response type in the servlet.
This is how my "hello world" servlet used to test this case finally works.
public class HolaMundo extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/css");
PrintWriter out = response.getWriter();
out.println("Hello World! entrada");
out.flush();
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
out.println("Hello World! salida");
out.flush();
}
}
I created servlet to download file from a server. In GWT I created a FormPanel and I am able to download a file.
Problem is, that I want to fire an event, when the file is ready. I tried to use onSubmitComplete event, but it isn't firing.
I found a suggestion, to change ContetType to "text/html", but still no luck. I found, that the problem lies in writing to OutputStream - when commented out, event is fired.
Here is my servlet code
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setHeader("Content-Disposition", "attachment; filename=File.xls");
HSSFWorkbook workbook = new HSSFWorkbook();
try {
workbook = fileCreator.getWorkbook();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
OutputStream out = response.getOutputStream();
workbook.write(out);
out.close();
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print("something");
response.flushBuffer();
}
So file is downloaded successfully, but event is not triggered. Even when I just get OutputStream and close it (without writing to it), event stops working.
When I remove whole "writing-to-output-stream" code, event works like a charm.
Any suggestions?
UPDATE
Here is code for FormPanel and its handlers, meby there is a problem?
Form:
downloadFileFormPanel.setEncoding(FormPanel.ENCODING_URLENCODED);
downloadFileFormPanel.setMethod(FormPanel.METHOD_POST);
VerticalPanel panel = new VerticalPanel();
panel.setWidth(UIConstatns.SIZE_100percent);
downloadFileFormPanel.setWidget(panel);
downloadFileButton = new Button(messages.EXPORT_LIMITS());
downloadFileButton.setWidth(UIConstatns.SIZE_100percent);
downloadFileButton.addStyleName("navigation-button");
panel.add(downloadFileButton);
Handlers
private void registerExportLimitsHandler() {
registerHandler(getView().getDownloadFileButton().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
getView().showLoadingDialog();
getDownloadFileForm().submit();
}
}));
}
private void registerFormSubmitCompleteHandler() {
getView().getDownloadFileForm().addSubmitCompleteHandler(new SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
Window.alert("download complete");
getView().hideLoadingDialog();
}
});
}
According to the Javadoc of ServletResponse#getWriter() you can either use response.getOutputStream() or response.getWriter() to write the body of the response, but not both. Furthermore it is better to set the status code of the response before writing the body. Please try the following:
// ...
response.setStatus(HttpServletResponse.SC_OK);
OutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
// response.getWriter().print("something");
// response.flushBuffer();
You did not post the line where you create your FormPanel so I'm not sure if this was your problem:
Looks like the FormPanel(String target) constructor does not work with the SubmitCompleteHandler. With the default constructor it seems to work.
Somewhere within my Wicket Link, that calls a Utility, which serves a report file,
generated by BIRT, I am getting an IllegalStateException.
From the Wicket page:
Link<Void> downloadLink = new Link<Void>("download") {
private static final long serialVersionUID = 1L;
#Override
public void onClick() {
HttpServletResponse response =
(HttpServletResponse)((WebResponse)getResponse()).getContainerResponse();
ReportUtility.getInstance().serveFile("myFileName.rptdesign", "pdf", response, null);
}
};
add (downloadLink);
From the ReportUtility.java:
public void serveFile(String reportDesignFile, String extType,
HttpServletResponse response, Map<String, Object> paramMap) {
InputStream is = null;
ServletOutputStream os = null;
try {
is = ReportUtility.class.getResourceAsStream(reportDesignFile);
os = response.getOutputStream();
IReportRunnable irr = engine.openReportDesign(is);
IRunAndRenderTask task = engine.createRunAndRenderTask(irr);
HTMLRenderOption options = new HTMLRenderOption();
options.setOutputFormat(extType);
options.closeOutputStreamOnExit(true);
options.setOutputStream(os);
// to force open/save/cancel with our specified filename
String outputFileName = createReportFileName(reportDesignFile, extType);
response.addHeader("Content-Disposition", "attachment;filename=" + outputFileName);
if (paramMap != null) {
task.setParameterValues(paramMap);
}
task.setRenderOption(options);
task.run();
}
catch (EngineException ex) {
logger.error("Engine Exception while serving file", ex);
throw new RuntimeException(ex);
}
catch (IOException ioex) {
logger.error("IO Exception while openning response output stream", ioex);
throw new RuntimeException(ioex);
}
finally {
try {
if (os != null)
os.close();
if (is != null)
is.close();
} catch (IOException e) {
// ignore
}
}
}
If it matters, the createReportFileName method appends today's date and the proper file extension to
the basename of the report design file, i.e. "myFileName.rptdesign" becomes "myFileName_04_24_2012.pdf"
Here is the statck trace:
Apr 24, 2012 9:35:04 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:435)
at org.apache.wicket.protocol.http.servlet.ServletWebResponse.sendRedirect(ServletWebResponse.java:230)
at org.apache.wicket.protocol.http.BufferedWebResponse$SendRedirectAction.invoke(BufferedWebResponse.java:392)
at org.apache.wicket.protocol.http.BufferedWebResponse.writeTo(BufferedWebResponse.java:580)
at org.apache.wicket.protocol.http.HeaderBufferingWebResponse.flush(HeaderBufferingWebResponse.java:89)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:195)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:241)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)
It is important to state that this does not effect the operation: the user clicks, the open/save/cancel appears,
the file comes, and looks very pretty. After ward, however, whatever the user tries to do next, sends to
our error page with a StalePageException. After that, everything returns to normal again.
I suspect this involves the HttpServletResponse, or perhaps how I am getting it from Wicket. However, that portion of
my code that adds the file to the response with the header is copied almost exactly from BIRT's tutorials. (Maybe BIRT and Wicket
just don't like each other.)
I note that none of my own code shows in the stack trace. Also, I have tried to "catch" the IllegalStateException in
a handful of places, including the onClick, the serveFile, and even my Wicket Application, all without
success. Of course, even if I could catch it, I would prefer to have never caused it in the first place.
A better way to deliver the report will be to implement your own ResourceStream (...implements IResourceStream). Your implementation returns the generated report when the user click.
Here is some example how to add a wicket link that streams the report to the client:
add(new Link("reportAsPdfButton") {
#Override
public void onClick() {
BirtReportResourceStream brrs = new BirtReportResourceStream();
getRequestCycle().scheduleRequestHandlerAfterCurrent(new ResourceStreamRequestHandler(brrs, "your_report_name.pdf"));
}
});
Here is a short sample hot to implement the IResourceStream:
public class BirtReportResourceStream implements IResourceStream {
private byte[] content = null;
...
public BirtReportResourceStream() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
EngineConfig config = new EngineConfig();
config.setEngineHome(basePath + "/WEB-INF/ext_lib/");
try {
Platform.startup(config);
IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
IReportEngine engine = factory.createReportEngine(config);
IReportRunnable report = engine.openReportDesign("path/to/your/report-definiton.rpt");
IRunAndRenderTask task = engine.createRunAndRenderTask(report);
if (null != getParameter()) {
task.setParameterValues(getParameter());
}
PDFRenderOption options = new PDFRenderOption();
options.setOutputFormat(format.toString().toLowerCase());
options.setOutputStream(baos);
task.setRenderOption(options);
task.run();
task.close();
} catch (BirtException e) {
// handle the exception...
}
content = baos.toByteArray();
}
public InputStream getInputStream() throws ResourceStreamNotFoundException {
return new ByteArrayInputStream(content);
}
...
}
There are some more methods to implement but they are simple. The most complex part was to find out how to create the report and stream it into an byte array and how to stream it to the client. These two methods are shown above.
Hope it helps.