繁体   English   中英

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

[英]Streaming a file download in managed bean action invoked by a dynamically created CommandButton has no effect

所以我有一种方法,可以通过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,command button是扩展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)

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

有人看到我在做错误的假设吗?

谢谢您的时间,迈克

您无处不在将文件写入输出流。 为此,您应该将文件写入输出流。 这是为我工作的示例代码。 希望对您有帮助。

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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM