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

时间:2021-08-27 09:52:38

I have a requirement like: I am making an AJAX request to pass some data to server. In my server I am creating a file using that data.

我有这样的需求:我正在发出一个AJAX请求,以便向服务器传递一些数据。在我的服务器中,我正在使用这些数据创建一个文件。

"Now problem is the file is not getting downloaded to client-side".

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

(I am using Apache POI API to create excel file from the given data). Can any one will help me to do this ?

(我使用Apache POI API从给定的数据创建excel文件)。有人能帮我做这件事吗?

Here is my code:

这是我的代码:

(Code to make AJAX request)

(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(-,-) method

Java代码特性(-,-)方法

/*
*   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(-, -, -) method to create excel file /

/ * ImportBulkDataUtil。下载(-、-、-)方法来创建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");
        }
    }

Can anyone help me ?

谁能帮帮我吗?

5 个解决方案

#1


7  

There could be 2 issues. Either you don't send file at all or ajax is not downloading it.

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

From your code I can see that you writing file in response's output stream so I suspect that part is working. Maybe you can open browser developer tool to see response from server if it contains data in response body.

从您的代码中,我可以看到您在响应的输出流中编写文件,因此我怀疑该部分正在工作。如果响应体中包含数据,您可以打开browser developer工具查看服务器的响应。

Second part is complicated because from nature of JS (security reason) you cannot download directly in JS itself (download will not start itself).

第二部分比较复杂,因为从JS(出于安全原因)的性质来看,不能直接用JS本身下载(下载本身不会启动)。

You need to use either iframe and append file url into and submit form to start download

您需要使用iframe和追加文件url并提交表单以开始下载

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

or

you can use new HTML5 FileAPI to do this for you in one request. Just specify blob (responseType: 'blob') type for response, convert URL from response body, append it to href attribute of newly created anchor <a> element and click on it.

您可以使用新的HTML5 FileAPI在一个请求中为您实现这一点。只需指定blob (responseType: 'blob')类型作为响应,从响应主体转换URL,将其附加到新创建的锚的href属性元素并单击它。

See this post for more details.

有关更多细节,请参阅本文。

Hope that helps.

希望有帮助。

#2


2  

You can write the contents of the POI HSSFWorkbook to a ByteArrayOutputStream and then use the toByteArray() method of the stream in Liferay's PortletResponseUtil sendFile() method as follows:

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

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

instead of writing directly to the resourceResponse.

而不是直接写信给参考资源。

However, probably for security reasons, (Javascript can not directly write files to a client) you can not do this via Ajax.

但是,可能出于安全原因(Javascript不能直接向客户端写入文件),您不能通过Ajax实现这一点。

You could alternatively save the raw data that you calculate in your JS code to a hidden input and pass that to the server via a regular form submit.

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

#3


2  

I think it's just your ajax command whose don't follow requirements. See jquery ajax documentation.

我认为这只是您的ajax命令,它不遵循需求。看到jquery ajax文档。

It's seems ajax jquery complains xml data download but it's not accordingly with excel data format.

似乎ajax jquery会抱怨xml数据下载,但与excel数据格式不同。

Set the dataType to "text" in ajax and does the good MIME type before to send the generated file to client..it's make the excel file download to be interpreted by the browser as a real excel file.

将数据类型设置为ajax中的“text”,并在将生成的文件发送到客户端之前执行良好的MIME类型。它使excel文件下载被浏览器解释为一个真正的excel文件。

#4


2  

just have the request as GET, return the bytestream of file in response and set the headers accordingly (depending on the format of you file excel/pdf) and then at client side just open the response in new tab the browser would start the file download.

只要将请求设置为GET,返回文件的bytestream作为响应,并相应地设置头部(取决于文件excel/pdf的格式),然后在客户端打开new选项卡中的响应,浏览器就会启动文件下载。

#5


1  

Just call the following function with parameters :

用参数调用如下函数:

url - where you want to request for file
data - incase you want to send some data
pageIndex - div id where u want to append iframe and than it will be deleted without # .

url——你想要请求文件数据的地方——如果你想发送一些数据页面索引——div id,你想要添加iframe,而它将在没有#的情况下被删除。

this.ajaxDownload = function(url, data,pageId) {
                pageId = '#' + pageId;
                 if ($(pageId + ' #download_iframe').length == 0) {
                     $("<iframe id='download_iframe' style='display: none' src='about:blank'></iframe>").appendTo(pageId);
                 }

                 var input = "<input type='hidden' name='requestJson' value='" + JSON.stringify(data) + "'>";

                 var iframe_html = "<html>"+
                     "<head>"+
                     "</head>"+
                     "<body>"+
                     "<form id='downloadForm' method='POST' action='" + url +"'>" +input+ "</form>" +
                     "</body>"+
                     "</html>";

                 var ifrm = $(pageId + ' #download_iframe')[0].contentWindow.document;
                 ifrm.open();
                 ifrm.write(iframe_html);
                 ifrm.close();

                 $(pageId + ' #download_iframe').contents().find("#downloadForm").submit();
 }

#1


7  

There could be 2 issues. Either you don't send file at all or ajax is not downloading it.

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

From your code I can see that you writing file in response's output stream so I suspect that part is working. Maybe you can open browser developer tool to see response from server if it contains data in response body.

从您的代码中,我可以看到您在响应的输出流中编写文件,因此我怀疑该部分正在工作。如果响应体中包含数据,您可以打开browser developer工具查看服务器的响应。

Second part is complicated because from nature of JS (security reason) you cannot download directly in JS itself (download will not start itself).

第二部分比较复杂,因为从JS(出于安全原因)的性质来看,不能直接用JS本身下载(下载本身不会启动)。

You need to use either iframe and append file url into and submit form to start download

您需要使用iframe和追加文件url并提交表单以开始下载

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

or

you can use new HTML5 FileAPI to do this for you in one request. Just specify blob (responseType: 'blob') type for response, convert URL from response body, append it to href attribute of newly created anchor <a> element and click on it.

您可以使用新的HTML5 FileAPI在一个请求中为您实现这一点。只需指定blob (responseType: 'blob')类型作为响应,从响应主体转换URL,将其附加到新创建的锚的href属性元素并单击它。

See this post for more details.

有关更多细节,请参阅本文。

Hope that helps.

希望有帮助。

#2


2  

You can write the contents of the POI HSSFWorkbook to a ByteArrayOutputStream and then use the toByteArray() method of the stream in Liferay's PortletResponseUtil sendFile() method as follows:

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

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

instead of writing directly to the resourceResponse.

而不是直接写信给参考资源。

However, probably for security reasons, (Javascript can not directly write files to a client) you can not do this via Ajax.

但是,可能出于安全原因(Javascript不能直接向客户端写入文件),您不能通过Ajax实现这一点。

You could alternatively save the raw data that you calculate in your JS code to a hidden input and pass that to the server via a regular form submit.

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

#3


2  

I think it's just your ajax command whose don't follow requirements. See jquery ajax documentation.

我认为这只是您的ajax命令,它不遵循需求。看到jquery ajax文档。

It's seems ajax jquery complains xml data download but it's not accordingly with excel data format.

似乎ajax jquery会抱怨xml数据下载,但与excel数据格式不同。

Set the dataType to "text" in ajax and does the good MIME type before to send the generated file to client..it's make the excel file download to be interpreted by the browser as a real excel file.

将数据类型设置为ajax中的“text”,并在将生成的文件发送到客户端之前执行良好的MIME类型。它使excel文件下载被浏览器解释为一个真正的excel文件。

#4


2  

just have the request as GET, return the bytestream of file in response and set the headers accordingly (depending on the format of you file excel/pdf) and then at client side just open the response in new tab the browser would start the file download.

只要将请求设置为GET,返回文件的bytestream作为响应,并相应地设置头部(取决于文件excel/pdf的格式),然后在客户端打开new选项卡中的响应,浏览器就会启动文件下载。

#5


1  

Just call the following function with parameters :

用参数调用如下函数:

url - where you want to request for file
data - incase you want to send some data
pageIndex - div id where u want to append iframe and than it will be deleted without # .

url——你想要请求文件数据的地方——如果你想发送一些数据页面索引——div id,你想要添加iframe,而它将在没有#的情况下被删除。

this.ajaxDownload = function(url, data,pageId) {
                pageId = '#' + pageId;
                 if ($(pageId + ' #download_iframe').length == 0) {
                     $("<iframe id='download_iframe' style='display: none' src='about:blank'></iframe>").appendTo(pageId);
                 }

                 var input = "<input type='hidden' name='requestJson' value='" + JSON.stringify(data) + "'>";

                 var iframe_html = "<html>"+
                     "<head>"+
                     "</head>"+
                     "<body>"+
                     "<form id='downloadForm' method='POST' action='" + url +"'>" +input+ "</form>" +
                     "</body>"+
                     "</html>";

                 var ifrm = $(pageId + ' #download_iframe')[0].contentWindow.document;
                 ifrm.open();
                 ifrm.write(iframe_html);
                 ifrm.close();

                 $(pageId + ' #download_iframe').contents().find("#downloadForm").submit();
 }