PDF generation using iText in Struts-2 : result ty

2019-01-25 21:17发布

问题:

My requirement is to generate PDF file using iText, I use below code to create a sample PDF

Document document = new Document();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter.getInstance(document, baos);
document.open();
document.add(new Paragraph("success PDF FROM STRUTS"));
document.close();
ServletOutputStream outputStream = response.getOutputStream() ;
baos.writeTo(outputStream);
response.setHeader("Content-Disposition", "attachment; filename=\"stuReport.pdf\"");
response.setContentType("application/pdf");
outputStream.flush();
outputStream.close();

If you see in the above code, iText is not using any inputStream parameter, rather it is writing directly to response's outputstream. Whereas struts-2 is mandating us to use InputStream parameter (see the configuration below)

<action name="exportReport" class="com.export.ExportReportAction">
    <result name="pdf" type="stream">
        <param name="inputName">inputStream</param>
        <param name="contentType">application/pdf</param>
        <param name="contentDisposition">attachment;filename="sample.pdf"</param>
        <param name="bufferSize">1024</param>
    </result>
</action>

I know that my class should have getters and setters for inputStream and i have that too in the class mentioned in struts-configuration

private InputStream inputStream;
public InputStream getInputStream() {
    return inputStream;
}

public void setInputStream(InputStream inputStream) {
    this.inputStream = inputStream;
}

But since iText doesn't really need inputstream rather it is writing directly to response's outputstream, i get exceptions since am not setting anything for the inputStream parameter.

Please let me know how to use iText code in struts-2 having the resultType as stream

Thanks

回答1:

Found solution to this.

The method in the action which performs this PDF export can be void. The result type configuration is not needed while we are writing directly to response's outputstream

for example, have your action class this way

Class ExportReportAction extends ActionSupport {
  public void exportToPdf() { // no return type
    try {
        Document document = new Document();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, baos);
        document.open();
        document.add(new Paragraph("success PDF FROM STRUTS"));
        document.close(); 
        ServletOutputStream outputStream = response.getOutputStream() ; 
        baos.writeTo(outputStream); 
        response.setHeader("Content-Disposition", "attachment; filename=\"stuReport.pdf\""); 
        response.setContentType("application/pdf"); 
        outputStream.flush(); 
        outputStream.close(); 
    }catch (Exception e) {
        //catch
    }

  } 
}

and have your struts-configuration this way

<action name="exportReport" class="com.export.ExportReportAction"> 
 <!-- NO NEED TO HAVE RESULT TYPE STREAM CONFIGURATION-->
</action>

this works cool !!!

Thanks for all who attempted to answer this question



回答2:

Main Answer:

You can also return NONE or return null as explained in the Apache docs:

Returning ActionSupport.NONE (or null) from an action class method causes the results processing to be skipped. This is useful if the action fully handles the result processing such as writing directly to the HttpServletResponse OutputStream.

Source: http://struts.apache.org/release/2.2.x/docs/result-configuration.html


Example:

O'Reilly offers a tutorial on Dynamically Creating PDFs in a Web Application using Servlets (S.C. Sullivan, 2003). It can be converted to a Struts2 action class as shown below.

It is good to have a helper class like PDFGenerator to create the PDF for you and return it as a ByteArrayOutputStream.

PDFGenerator class:

import java.io.ByteArrayOutputStream;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

public class PDFGenerator {

    public ByteArrayOutputStream generatePDF() throws DocumentException {

        Document doc = new Document();
        ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();            
        PdfWriter pdfWriter = PdfWriter.getInstance(doc, baosPDF);

        try {           
            doc.open();         

            // create pdf here
            doc.add(new Paragraph("Hello World"));

        } catch(DocumentException de) {
            baosPDF.reset();
            throw de;

        } finally {
            if(doc != null) {
                doc.close();
            }

            if(pdfWriter != null) {
                pdfWriter.close();
            }
        }

        return baosPDF;
    }
}

You can now call it in your action class.

ViewPDFAction class:

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletResponseAware;
import com.yoursite.helper.PDFGenerator;
import com.opensymphony.xwork2.ActionSupport;

public class ViewPDFAction extends ActionSupport
    implements ServletResponseAware {

    private static final long serialVersionUID = 1L;    
    private HttpServletResponse response;

    @Override
    public String execute() throws Exception {

        ByteArrayOutputStream baosPDF = new PDFGenerator().generatePDF();    
        String filename = "Your_Filename.pdf"; 

        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition",
            "inline; filename=" + filename); // open in new tab or window           
        response.setContentLength(baosPDF.size());

        OutputStream os = response.getOutputStream();
        os.write(baosPDF.toByteArray());
        os.flush();
        os.close();
        baosPDF.reset();

        return NONE; // or return null
    }

    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response = response;       
    }
}

web.xml:

<mime-mapping>
    <extension>pdf</extension>
    <mime-type>application/pdf</mime-type>
</mime-mapping>

struts.xml:

<action name="viewpdf" class="com.yoursite.action.ViewPDFAction">
    <!-- NO CONFIGURATION FOR RESULT NONE -->
</action>