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

Posted

技术标签:

【中文标题】通过发送ajax请求下载Excel文件【英文标题】:Download Excel File by sending ajax request 【发布时间】:2011-10-16 07:32:48 【问题描述】:

我使用 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) throws 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();
        

      


【问题讨论】:

【参考方案1】:

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

yourpage.php 是您生成 Excel 文件的位置。

【讨论】:

【参考方案2】:

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

【讨论】:

您能否举例说明您是如何实现的? 他的意思是他生成了文件,用唯一的名称(或 ID)保存它,然后使用指向该文件的直接链接获取它。这可以在文件系统中完成,也可以使用 Web 应用程序中的下载脚本完成。

以上是关于通过发送ajax请求下载Excel文件的主要内容,如果未能解决你的问题,请参考以下文章

POI导出Excel不弹出保存提示_通过ajax异步请求(post)到后台通过POI导出Excel

下载 excel 文件的 ajax 请求显示我被截断的响应

下载 excel 文件的 ajax 请求显示我被截断的响应

用ajax下载字节流形式的excel文件

下载请求发送成功,无下载提示,下载失败

SSM excel文件的导入导出