2

I am trying to return an Excel sheet from my struts2 action class.

I am not sure what result-type should I be using? Has anyone tried to return an excel from struts2 action class?
I would like the user to be presented with open/save/cancel dialog box

Roman C
  • 49,761
  • 33
  • 66
  • 176

3 Answers3

7

Omnipresent covered what you need in struts.xml. I'm adding an example with the Action as well:

InputStream excelStream
String contentDisposition
String documentFormat = "xlsx"

String excel() {

    ServletContext servletContext = ServletActionContext.getServletContext()
    String filePath = servletContext.getRealPath("/WEB-INF/template/excel/mytemplate.${documentFormat}")

    File file = new File(filePath)
    Workbook wb = WorkbookFactory.create(new FileInputStream(file))

    Sheet sheet = wb.getSheetAt(0)

<write to excel file>

    ByteArrayOutputStream baos = new ByteArrayOutputStream()
    wb.write(baos)
    excelStream = new ByteArrayInputStream(baos.toByteArray())
    contentDisposition = "filename=\"myfilename.${documentFormat}\""

    return SUCCESS
}

String getExcelContentType() {
    return documentFormat == "xlsx" ? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" : "application/vnd.ms-excel"
}

I'm using the poi model: org.apache.poi.ss.usermodel.

You can replace "xlsx" with "xls" if you want.

struts.xml:

<action name="myaction" class="com.example.MyAction" method="excel">
        <result type="stream">
            <param name="contentType">${excelContentType}</param>
            <param name="inputName">excelStream</param>
            <param name="contentDisposition">contentDisposition</param>
            <param name="bufferSize">1024</param>
        </result>
    </action>

(add semicolons and stuff to translate to valid Java)

rlovtang
  • 4,860
  • 2
  • 30
  • 30
  • This is kind of late, but I need help on the same issue. Firstly, In this case a file is first created on the server side and then streamed to the client side. Is it possible to directly stream the contents of the excel sheet to client side. Secondly which class have you used for the result-type 'stream'. Please help me out. Thanks!! – kanishk Feb 15 '12 at 09:07
  • 1
    'stream' is org.apache.struts2.dispatcher.StreamResult which resides in struts2-core and is defined as a result-type in struts-default.xml (also in struts2-core). – rlovtang Feb 15 '12 at 10:47
  • Regarding streaming, I have no clue. Might have something to do with bufferSize, maybe a lower value will stream more directly? – rlovtang Feb 15 '12 at 10:50
  • Ok. Got the first part. Thanks!! – kanishk Feb 16 '12 at 04:48
5

You can utilize the Stream Result type

an Example will look like this:

<result name="excel" type="stream">
    <param name="contentType">application/vnd.ms-excel</param>
    <param name="inputName">excelStream</param>
    <param name="contentDisposition">attachment; filename="${fileName}"</param>
    <param name="bufferSize">1024</param>
    <param name="contentLength">${contentLength}</param>
 </result>

excelStream will be a method in your action class, contentLength will be length of the stream, fileName will be a getter which will return back the name of the file.

Omnipresent
  • 29,434
  • 47
  • 142
  • 186
  • And for xlsx, use contentType application/vnd.openxmlformats-officedocument.spreadsheetml.sheet – rlovtang Aug 25 '10 at 17:35
  • This is the better of the two answers because the user asked 'I would like the user to be presented with open/save/cancel dialog box'. The `attachment;` portion in `contentDisposition` is necessary to force the browser to always open the dialog. Without it, the browser may try to render the material itself if it is so configured. – demongolem May 26 '12 at 14:34
0

If you need to dynamically generate an Excel file using POI/HSSF and return in Struts 2,

JSP

<s:url action="DownloadExcel.action" var="downloadUrl">
</s:url>
<s:a href="%{downloadUrl}">Click to Download</s:a>

Action Method

@Action(value = "DownloadExcel")
public void download() throws Exception {
    
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();
    
    String filename = "report.xlsx"; // or any other filename strategy
    String mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    String characterEncoding = response.getCharacterEncoding();
    if (characterEncoding != null) {
        mimeType += "; charset=" + characterEncoding;
    }
    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition", "attachment;filename=" + filename);

    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.getSheetAt(0);
    // Fill out workbook as necessary... (simple example)
    XSSFRow row = sheet.createRow(0);
    XSSFCell cell = row.createCell(0);
    cell.setCellValue("test");
    //...

    ServletOutputStream out = null;
    try {
        out = response.getOutputStream();
        workbook.write(out);
        workbook.close();
    } catch (IOException e) {
        log.error("Failed to write into response - fileName=" + filename + ", mimeType=" + mimeType, e);
    }
    finally {
        if (out != null) {
            out.flush();
            out.close();
        }
    }
}
gene b.
  • 10,512
  • 21
  • 115
  • 227