如何从 Liferay serveResource(-, -) 方法中的 AJAX 请求下载文件

2022-09-02 01:54:27

我有一个要求,比如:我正在发出AJAX请求,将一些数据传递给服务器。在我的服务器中,我正在使用该数据创建一个文件。

“现在的问题是文件没有下载到客户端”。

(我正在使用Apache POI API从给定的数据创建excel文件)。任何人都可以帮我这样做吗?

这是我的代码:

(发出 AJAX 请求的代码)

<script>
    function downloadUploadedBacklogs () {

        try {
            var table_data = [];

            var count = jQuery("#backlogTable tr:first td" ).length;
            jQuery("#<portlet:namespace/>noOfColumns").val(count);
            var index = 0;
            jQuery('tr').each(function(){

                var row_data = '';
                jQuery('td', this).each(function(){
                    row_data += jQuery(this).text() + '=';   
                });   
                table_data.push(row_data+";");

            });
            jQuery("#<portlet:namespace/>backlogDataForDownload").val(table_data);
            jQuery("#<portlet:namespace/>cmd").val("downloadUploadedBacklogs");
            alert('cmd: ' + jQuery("#<portlet:namespace/>cmd").val());  
            var formData = jQuery('#<portlet:namespace/>backlogImportForm').serialize();

            jQuery.ajax({
                url:'<%=resourceURL%>',
                data:formData,
                type: "post",
                success: function(data) {

                }
            });
            alert('form submitted');

        } catch(e) {
            alert('eroor: ' + e);
        }
    };
</script>

Java code serveResource(-,-) 方法

/*
*   serveResource(-, -) method to process the client request
*/
public void serveResource(ResourceRequest resourceRequest,
            ResourceResponse resourceResponse) throws IOException,
            PortletException {


        String cmd = ParamUtil.getString(resourceRequest,"cmd");
        System.out.println("**********************cmd*************"+cmd);

        if(cmd!="") {
            if("downloadUploadedBacklogs".equalsIgnoreCase(cmd)){

                String backlogData = ParamUtil.getString(resourceRequest, "backlogDataForDownload");
                ImportBulkDataUtil.downloadUploaded("Backlogs", resourceRequest,resourceResponse);
            } 
        }
}

/ * ImportBulkDataUtil.downloadUploaded(-, -, -) 创建excel文件的方法 /

public static void downloadUploaded(String schema, ResourceRequest resourceRequest,ResourceResponse resourceResponse) {

        String excelSheetName = ParamUtil.getString(resourceRequest,"excelSheetName");

        try {
            resourceResponse.setContentType("application/vnd.ms-excel");
            resourceResponse.addProperty(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+excelSheetName+"_Template.xls");

            OutputStream outputStream=resourceResponse.getPortletOutputStream();
            //converting the POI object as excel readble object
            HSSFWorkbook objHSSFWorkbook=new HSSFWorkbook();
            HSSFSheet objHSSFSheet=objHSSFWorkbook.createSheet(excelSheetName+"_Template");

            //set the name of the workbook 
            Name name=objHSSFWorkbook.createName();
            name.setNameName(excelSheetName+"_Template");

            objHSSFSheet.autoSizeColumn((short)2);

            // create freeze pane (locking) top row
            objHSSFSheet.createFreezePane(0, 1);

            // Setting column width
            String excelData = StringPool.BLANK;
            if((schema.equalsIgnoreCase("Backlogs"))){
                System.out.println("Inside BacklogsCreation..........");
                objHSSFSheet.setColumnWidth(0, 10000);
                objHSSFSheet.setColumnWidth(1, 7000);
                objHSSFSheet.setColumnWidth(2, 7000);
                objHSSFSheet.setColumnWidth(3, 7000);
                objHSSFSheet.setColumnWidth(4, 7000);
                objHSSFSheet.setColumnWidth(5, 5000);
                objHSSFSheet.setColumnWidth(6, 5000);
                objHSSFSheet.setColumnWidth(7, 7000);
                objHSSFSheet.setColumnWidth(8, 7000);
                excelData = ParamUtil.getString(resourceRequest,"backlogDataForDownload");
            }
            System.out.println("downloadUploaded excelTableData: " + excelData);

             // Header creation logic

            HSSFRow objHSSFRowHeader = objHSSFSheet.createRow(0);
            objHSSFRowHeader.setHeightInPoints((2*objHSSFSheet.getDefaultRowHeightInPoints()));
            CellStyle objHssfCellStyleHeader = objHSSFWorkbook.createCellStyle();
            objHssfCellStyleHeader.setFillBackgroundColor((short)135);
            objHssfCellStyleHeader.setAlignment(objHssfCellStyleHeader.ALIGN_CENTER);
            objHssfCellStyleHeader.setWrapText(true);

            // Apply font styles to cell styles
            HSSFFont objHssfFontHeader = objHSSFWorkbook.createFont();
            objHssfFontHeader.setFontName("Arial");
            objHssfFontHeader.setColor(HSSFColor.WHITE.index);

            HSSFColor lightGrayHeader =  setColor(objHSSFWorkbook,(byte) 0x00, (byte)0x20,(byte) 0x60);
            objHssfCellStyleHeader.setFillForegroundColor(lightGrayHeader.getIndex());
            objHssfCellStyleHeader.setFillPattern(CellStyle.SOLID_FOREGROUND);

            objHssfFontHeader.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            objHssfFontHeader.setFontHeightInPoints((short)12);
            objHssfCellStyleHeader.setFont(objHssfFontHeader);
            objHssfCellStyleHeader.setWrapText(true);

            // first column about Backlog title
            HSSFCell objBacklogTitleCell = objHSSFRowHeader.createCell(0);
            objBacklogTitleCell.setCellValue("Backlog");
            objBacklogTitleCell.setCellStyle(objHssfCellStyleHeader);   

            // second column about Description
            HSSFCell objBacklogDescCell = objHSSFRowHeader.createCell(1);
            objBacklogDescCell.setCellValue("Description");
            objBacklogDescCell.setCellStyle(objHssfCellStyleHeader);

            // third column about Project
            HSSFCell objProjectNameCell = objHSSFRowHeader.createCell(2);
            objProjectNameCell.setCellValue("Project");
            objProjectNameCell.setCellStyle(objHssfCellStyleHeader);
            setComment("Project which the backlog belongs to", objProjectNameCell);

            // fourth column about Category
            HSSFCell objCategoryNameCell = objHSSFRowHeader.createCell(3);
            objCategoryNameCell.setCellValue("Category");
            objCategoryNameCell.setCellStyle(objHssfCellStyleHeader);
            setComment("Category which the backlog belongs to (i.e. Bug, New Requirement, Enhancement)", objCategoryNameCell);

            // fifth column about Group
            HSSFCell objGroupNameCell = objHSSFRowHeader.createCell(4);
            objGroupNameCell.setCellValue("Group");
            objGroupNameCell.setCellStyle(objHssfCellStyleHeader);
            setComment("Group which the backlog belongs to", objGroupNameCell);

            // sixth column about Est. Start Date
            HSSFCell objEstStartDtCell = objHSSFRowHeader.createCell(5);
            objEstStartDtCell.setCellValue("Est. Start Date");
            objEstStartDtCell.setCellStyle(objHssfCellStyleHeader);
            setComment("Date Format: dd/mm/yyyy", objEstStartDtCell);

            // seventh column about Est. End Date
            HSSFCell objEstEndDtCell = objHSSFRowHeader.createCell(6);
            objEstEndDtCell.setCellValue("Est. End Date");
            objEstEndDtCell.setCellStyle(objHssfCellStyleHeader);
            setComment("Date Format: dd/mm/yyyy", objEstEndDtCell);

            // fifth column about Group
            HSSFCell objStatusCell = objHSSFRowHeader.createCell(7);
            objStatusCell.setCellValue("Status");
            objStatusCell.setCellStyle(objHssfCellStyleHeader);

            String excelTableDataRecords[] = excelData.split(";");
            for(int i=1; i<excelTableDataRecords.length; i++) {

                HSSFRow objHSSFRow = objHSSFSheet.createRow(i);
                objHSSFRow.setHeightInPoints((2*objHSSFSheet.getDefaultRowHeightInPoints()));

                excelTableDataRecords[i] = excelTableDataRecords[i].substring(0, (excelTableDataRecords[i].length()-2));
                if(excelTableDataRecords[i].charAt(0) == ',') {
                    excelTableDataRecords[i] = excelTableDataRecords[i].substring(1, (excelTableDataRecords[i].length()));
                }
                String excelTableColumns[] = excelTableDataRecords[i].split("::");

                for(int j=0; j<excelTableColumns.length; j++) {

                        // Apply font styles to cell styles
                        HSSFFont objHssfFont = objHSSFWorkbook.createFont();
                        objHssfFont.setFontName("Arial");
                        CellStyle objHssfCellStyle = objHSSFWorkbook.createCellStyle();
                        objHssfFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
                        objHssfFont.setColor(HSSFColor.BLACK.index);
                        objHssfFont.setFontHeightInPoints((short)10);

                        objHssfCellStyle.setWrapText(true);
                        objHssfCellStyle.setFont(objHssfFont);
                        // other column about Backlog title
                        HSSFCell objNewHSSFCellFirstNameAdd = objHSSFRow.createCell(j);
                        objNewHSSFCellFirstNameAdd.setCellValue(excelTableColumns[j]);
                        objNewHSSFCellFirstNameAdd.setCellStyle(objHssfCellStyle);
                }
            }

            objHSSFWorkbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Exception raised in downloadUploaded() method to download uploaded excel data");
        }
    }

任何人都可以帮助我吗?


答案 1

可能有2个问题。要么你根本不发送文件,要么ajax没有下载它。

从你的代码中,我可以看到你在响应的输出流中编写文件,所以我怀疑该部分正在工作。也许您可以打开浏览器开发人员工具,以查看来自服务器的响应(如果它包含响应正文中的数据)。

第二部分很复杂,因为从JS的性质(安全原因)来看,你不能直接在JS本身下载(下载不会自己启动)。

您需要使用 iframe 并将文件 URL 附加到并提交表单中才能开始下载

$("body").append("<iframe src='" + data.message + "' style='display: none;' ></iframe>");

您可以使用新的HTML5在一个请求中为您执行此操作。只需指定()响应类型,从响应正文转换URL,将其附加到新创建的锚元素的href属性,然后单击它。FileAPIblobresponseType: 'blob'<a>

有关更多详细信息,请参阅帖子。

希望有所帮助。


答案 2

您可以将 POI HSSFWorkbook 的内容写入 ByteArrayOutputStream,然后在 Liferay 的 PortletResponseUtil sendFile() 方法中使用流的 toByteArray() 方法,如下所示:

PortletResponseUtil.sendFile(resourceRequest, resourceResponse, "FILENAME", byteStream.toByteArray(), "CONTENT_TYPE");

而不是直接写入资源响应。

但是,可能出于安全原因,(Javascript不能直接将文件写入客户端)您无法通过Ajax执行此操作。

或者,您可以将在JS代码中计算的原始数据保存到隐藏的输入中,并通过常规表单提交将其传递给服务器。