在由动态创建的CommandButton调用的托管bean操作中流式传输文件无效

时间:2014-09-16 17:05:41

标签: jsf download

所以我有一个方法是在doGet(HttpServletRequest request, HttpServletResponse response)调用时正确创建一个包含大量数据的CSV文件,当我创建一个这样的按钮时调用该文件:

link = new HtmlOutputLink();
HtmlGraphicImage img = new HtmlGraphicImage(); 
img.setStyle("background-color: #FFFFFF;"); 
img.setTitle("Click to Export these requests to csv file"); 
img.setValue("../images/Export.PNG"); 
link.getChildren().add(img);
link.setValue(resp.encodeURL(Constants.TXT_ALL_DIV_TEAM_EXPORT_LINK)); 
cell = new DataTableCell();
cell.setType(CellType.DATA); 
cell.setFormat(new Format(Format.CENTER)); 
cell.addElement(link);
headerRow.addElement(cell);

当单击该按钮时,doGet方法然后调用创建CSV文件的方法(再次,从doGet调用正确的方法)。

但是,我必须将其从图像更改为CommandButton,命令按钮是一个扩展javax.faces.component.html.HtmlCommandButton包的自定义类,所以现在我有了这个:

HtmlOutputLink link = new HtmlOutputLink();
CommandButton alertsButton = new CommandButton();

alertsButton.setId(UI_EXPORT_ID);
alertsButton.setValue(UI_EXPORT_TXT);
alertsButton.setOnclick("javascript:showWaitLayer();jsCBDupdateComponent('" + "form" + "', this );");
alertsButton.setBlockSubmit(true);
alertsButton.setImmediate(true);
alertsButton.addActionListener(this);

link.getChildren().add(alertsButton);
cell = new DataTableCell();
cell.setType(CellType.DATA); 
cell.setFormat(new Format(Format.CENTER)); 
cell.addElement(link);
headerRow.addElement(cell);

当单击此按钮时,它调用processAction(),其中我实例化用于传入工作方法的HttpServletResponse。

FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
response.setContentType("application/octet-stream");
HomeController homeController = (HomeController) context.getApplication().createValueBinding("#{HomeController}").getValue(context);
homeController.createExportFile(response);

编辑:添加createExportFile方法,其中包含大量可读性。

EDIT2:我已经更改了createExportFile,因此不需要传入HttpServletResponse。这样,该方法对传入的参数没有任何依赖性。两个按钮(带有img的按钮和一个带有CommandButton的按钮)调用此方法并在完全相同的方法中无错误地运行。只有img按钮可以创建excel文件。

public void createExportFile()
        throws IOException, PersistenceException, SQLException {
    FacesContext context = FacesContext.getCurrentInstance();
    HttpServletResponse resp = (HttpServletResponse) context.getExternalContext().getResponse();
    resp.setContentType("application/octet-stream");
    resp.setContentLength(500 * this.getWorkAllDivDeptList().size());
    resp.setHeader("Content-Disposition", "attachment; filename=\""
            + "AllDivTeam.csv" + "\"");             Map<String, HashSet<String>> stateDateMap = new HashMap<String, HashSet<String>>();

    ArrayList<DynamicFieldInfo> txtFieldAllList = new ArrayList<DynamicFieldInfo>();
    RequestReader kanbanReader;

    try {
        //Get all of the data from the DB
    } catch (MidTierException mte) {
        mte.printStackTrace();
    }

    String rowTxt = getExportRowHdrTxt(txtFieldAllList, addlColCnt);
    response.getOutputStream().write(rowTxt.getBytes(), 0, rowTxt.length());
    kanbanReader = new RequestReader("");

    for (AllActiveWorkListInfo bwi : (ArrayList<AllActiveWorkListInfo>) this
            .getFilteredAllDivDeptList()) {
        HashSet<String> set = (HashSet<String>) stateDateMap.get(bwi.getMID());
        if (null != set && !set.isEmpty()) {
            Iterator<String> itr = set.iterator();
            while (itr.hasNext()) {
                rowTxt = getExportRowTxt(bwi, txtFieldAllList,
                        kanbanReader, (String) itr.next());
                response.getOutputStream().write(rowTxt.getBytes(), 0,
                        rowTxt.length());
            }
        } else {
            rowTxt = getExportRowTxt(bwi, txtFieldAllList, kanbanReader, "");
            response.getOutputStream().write(rowTxt.getBytes(), 0,
                    rowTxt.length());
        }

        if (count++ == 200) {
            response.getOutputStream().flush();
        }

    }
    response.getOutputStream().flush();
    response.getOutputStream().close();
}

添加标题:

(Request-Line)  POST /kanban/faces/kanbanRepAllDivDeptTickets HTTP/1.1
Accept  */*
Accept-Encoding gzip, deflate
Accept-Language en-us
Cache-Control   no-cache
Connection  Keep-Alive
Content-Length  530
Content-Type    application/x-www-form-urlencoded
Cookie  _cbdModemCheck=false; JSESSIONID=08ADA3D60982F9D13478AF729D6E5205; s_fid=24245A567AE4BB33-0F8E3B5CF3FBEED7
Host    localhost:8080
Referer http://localhost:8080/kanban/faces/kanbanRepAllDivDeptTickets
User-Agent  Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3)

当我进行调试时,它会完成所有创建csv的过程,就像从doGet调用时一样,但它永远不会打开下载或取消的对话框。它没有任何例外,我完全没有想法。

有谁看到我做出错误假设的地方?

谢谢你的时间, 麦克

1 个答案:

答案 0 :(得分:0)

您无法将文件写入输出流。您应该将文件写入输出流。 这是为我工作的示例代码。希望它可以帮到你。

int BUFSIZE = 4096;
int length = 0;
ServletOutputStream outStream = response.getOutputStream();
String mimeType = "text/csv";
response.setContentType(mimeType);
response.setContentLength((int)document.length());
String documentName = document.getName();
response.setHeader("Content-Disposition", "attachment; filename=\"" + yourCsvFileName +  "\"");

byte[] byteBuffer = new byte[BUFSIZE];
DataInputStream in = new DataInputStream(new FileInputStream(document));

while((null != in) && ((length = in.read(byteBuffer)) != -1)) {
    outStream.write(byteBuffer, 0, length);
}
in.close();
outStream.close();