通过发送ajax请求下载Excel文件

时间:2011-07-29 22:18:43

标签: jquery ajax spring excel download

我使用ajaxForm发送我的初始请求。调用该方法并设置所有响应,但是当我尝试打开窗口时,它再次重新触发请求。所以请求发送两次。收到的是我的请求。

 $('#reportForm').ajaxForm( {

       dataType :'json',
        type :'POST',
        url : 'report/initialRequest.html',

                beforeSubmit :validateSearchField,

                ifModified : true,
                success :function(data, textStatus, jqXHR){},
                complete : function(jqXHR, textStatus) {
                                           window.location.href = "report/initialRequest.html" + "?" +  $('#reportForm').formSerialize();
                            $.unblockUI();
                                           return false;
                 }      
         });     

我们是否可以停止发送第二个请求。这样做的全部目的是生成的报告太大,所以当用户提交请求jasper报告需要很长时间才能获取文件,因此用户不知道文件何时回来。所以我使用了一个块UI插件,当用户点击提交按钮时页面被阻止,一旦文件返回,我就会解锁页面。

或者任何机构对如何实现这一目标都有更好的想法。

控制器代码

@RequestMapping(" /report/initialRequest.html")

public  @ResponseBody Map<String, Object> handleInitialRequest
 (HttpSession session, HttpServletRequest request, HttpServletResponse response     ) {


 Collection<Results> results = getResults();

  Map<String,Object> requestMap = new HashMap<String,Object>();         
  try {
getReportDataAsExcel(session, request, response , results );
} catch (JRException e) {
        e.printStackTrace();
}


        requestMap.put("status", "SUCCESS");
        return requestMap;
}



@SuppressWarnings("unchecked")

public void getReportDataAsExcel(HttpSession session,HttpServletRequest request,HttpServletResponse response,Collection results)抛出JRException {

    JRDataSource reportSource = new JRBeanCollectionDataSource( results );

    Map parameters = new HashMap();

    JRAbstractLRUVirtualizer virtualizer = null;



//  JRSwapFile swapFile = new JRSwapFile( getServletContext().getRealPath("/reports/"), 1024, 1024);
    JRSwapFile swapFile = new JRSwapFile( getServletContext().getRealPath("/reports/operationalreports/"), 1024, 1024);
    virtualizer = new JRSwapFileVirtualizer(2, swapFile, true);

    parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);    


    //logger.debug(reportUrl);
    Resource mainReport = null;
    JasperDesign design = null;
    JasperReport compiledReport = null;
    JasperPrint outputReport = null;

    try {
       mainReport = getApplicationContext().getResource(reportUrl);

       if (!mainReport.exists()){
         throw new JRRuntimeException("File .jrxml was not found. The file must exists before compiling.");
       }

        InputStream reportInputStream = mainReport.getInputStream();
        design = JRXmlLoader.load(reportInputStream);
        compiledReport = JasperCompileManager.compileReport(design);


       long start = System.currentTimeMillis();
       logger.debug("Starting Time : " +  start);

        outputReport = JasperFillManager.fillReport(compiledReport, parameters, reportSource);

    logger.debug("Filling time : " + (System.currentTimeMillis() - start));
    writeExcel( session, request,  response,outputReport );


    if (virtualizer != null)
    {
        virtualizer.cleanup();
    }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@SuppressWarnings("unchecked")
public void writeExcel(HttpSession session,HttpServletRequest request, HttpServletResponse response, JasperPrint jasperPrint)  {    


    ByteArrayOutputStream reportOutputStream = new ByteArrayOutputStream(OUTPUT_BYTE_ARRAY_INITIAL_SIZE);

    JRExporter exporter = new JRXlsExporter();

    // Excel specific parameters
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, reportOutputStream);
    try {
        exporter.exportReport();
    } catch (JRException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }


    ServletOutputStream outputStream = null;
    InputStream is = null;
    byte[] res = reportOutputStream.toByteArray();

    try{ 
       response.setContentType(getResponseContentType());
   setResponseHeader(response);

    response.setContentLength(reportOutputStream.size());

       outputStream = response.getOutputStream();
       is = new ByteArrayInputStream(res);

       int iSize = 0;

       byte[] oBuff = new byte[OUTPUT_BYTE_ARRAY_INITIAL_SIZE];

        while ((iSize = is.read(oBuff)) != -1) {
           outputStream.write(oBuff, 0, iSize);

       }



       } catch ( Exception e){
           e.printStackTrace();
       }
      finally {

          try {
            outputStream.flush();
            outputStream.close();  
            response.flushBuffer();


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

      }

}

2 个答案:

答案 0 :(得分:1)

我们有一个生成Excel文件的完整页面请求。请求完成后,显示屏将包含指向生成的Excel文件的链接。我更改了此过程以通过Ajax调用Excel生成页面,但是当该过程完成时,它将生成的Excel文件的URL返回到请求页面。用户获得带有链接的对话框,他们可以在不运行Excel生成请求两次的情况下获取文件。你可以改变你的流程吗?

答案 1 :(得分:0)

你不需要AJAX;只需使用document.location="yourpage.php"

yourpage.php是生成Excel文件的地方。