22

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.

"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 ?

Here is my code:

(Code to make AJAX request)

<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

/*
*   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 /

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 ?

  • **[Please Refer this : Java Servlet Download File Example](http://www.codejava.net/java-ee/servlet/java-servlet-download-file-example)** – Neeraj Jain Mar 19 '15 at 08:15
  • I also tried the same with resourceURL. But as my data is changing dynamically so I need to update resourceURL param value. But when I am updating it than only partial data is going to my serveResource(-,-) method – Chandan Prakash Sharma Mar 19 '15 at 08:18
  • And one more problem that I identified with resourceURL is URL having some length limit. So it will make problem when data is huge.. – Chandan Prakash Sharma Mar 19 '15 at 08:22
  • Can you see some data send from server? Is it case you don't send data at all or just don't download file on client-side? – Mior Apr 23 '15 at 13:30
  • I can see the response data on console at client side – Chandan Prakash Sharma Apr 23 '15 at 13:43
  • So problem is just in ajax download file. See my answer below http://stackoverflow.com/a/29825334/4275217 – Mior Apr 23 '15 at 13:44

5 Answers5

7

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

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.

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

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

$("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.

See this post for more details.

Hope that helps.

Community
  • 1
  • 1
Mior
  • 821
  • 8
  • 16
  • Thank you for your suggestion, I will try and let you know – Chandan Prakash Sharma Apr 23 '15 at 13:45
  • We are using FileAPI so you can download file in single request compare to first approach where you need to hold file somewhere and send just it's url and make another request in order to download it. – Mior Apr 23 '15 at 14:42
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:

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.

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.

  • Hi Tryfon, Thank you for your reply.. I will try it and let you know the status – Chandan Prakash Sharma Mar 20 '15 at 04:34
  • I tried below (but it didn't solve my problem): ByteArrayOutputStream byteArrOStream= new ByteArrayOutputStream(); objHSSFWorkbook.write(byteArrOStream); PortletResponseUtil.sendFile(resourceRequest, resourceResponse, excelSheetName+"_Template.xls", byteArrOStream.toByteArray(), "application/vnd.ms-excel"); Can you put more lights on what I need to do next ... ? – Chandan Prakash Sharma Mar 20 '15 at 07:57
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.

vinayakj
  • 5,591
  • 3
  • 28
  • 48
2

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

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

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.

user1587368
  • 314
  • 2
  • 6
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 # .

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();
 }
VIVEK-MDU
  • 2,483
  • 3
  • 36
  • 63
KlwntSingh
  • 1,084
  • 8
  • 26
  • I am getting exception like: contentWindow undefined, ifrm.open(); // unable to open – Chandan Prakash Sharma Apr 24 '15 at 15:28
  • @ChandanPrakashSharma you are not sending pageId correct try to send the div id to it.you can make sure your that your page id is working well by debugging code at if condition where we check the length is equal to zero – KlwntSingh Apr 25 '15 at 06:53