在由动态创建的CommandButton调用的托管bean操作中对文件下载进行流式处理没有任何效果



所以我有一个方法,当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(),我在其中实例化用于传递到工作方法的HttpServlet响应。

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

EDIT:添加createExportFile方法,为了可读性去掉了很多。

EDIT2:我已经更改了createExportFile,因此不需要传入HttpServlet响应。这样,该方法就不依赖于传入的参数。这两个按钮(带有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的所有过程,但它从未打开对话框进行下载或取消。它没有任何例外,我完全没有想法。

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

感谢您抽出时间,Mike

将文件写入输出流是不可能的。您应该为此将文件写入输出流。这是为我工作的示例代码。希望它能帮助你。

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

相关内容

最新更新