2016-05-12 277 views
1

我正在使用asp.net/C#/HTML5/bootstrap开发一个网站。其中一项要求是将文档导出为Excel和/或PDF。我能出口(成功),使用下面的片段(这是Excel的片段):使用HttpContext.Current.Response导出导致问题

 HttpContext.Current.Response.ContentType = "application/octet-stream"; 
     HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8; 
     HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + filename); 
     HttpContext.Current.Response.BinaryWrite(xlsBytes); 
     HttpContext.Current.Response.Flush(); 
     HttpContext.Current.Response.End(); 

我遇到的问题是,这个运行后,它似乎停止页面生命周期死在它的轨道。举个例子,用户点击导出按钮,它调用JavaScript代码抛出了一个“请等待”模态对话框并提交表单:

<script src="../Scripts/waitingFor.js"></script> 

<script type="text/javascript"> 
    function pleaseWait() { 
     waitingDialog.show("Building File<br/>...this could take a minute", { dialogSize: "sm", progressType: "warning" }); 

     form = document.getElementById("frm_contentMaster"); 
     form.submit(); 
    } 
</script> 

的JavaScript包括文件:

/** 
* Module for displaying "Waiting for..." dialog using Bootstrap 
* 
* @author Eugene Maslovich <[email protected]> 
*/ 

(function (root, factory) { 
    'use strict'; 

    if (typeof define === 'function' && define.amd) { 
     define(['jquery'], function ($) { 
      return (root.waitingDialog = factory($)); 
     }); 
    } 
    else { 
     root.waitingDialog = root.waitingDialog || factory(root.jQuery); 
    } 
}(this, function ($) { 

'use strict'; 

/** 
* Dialog DOM constructor 
*/ 
function constructDialog($dialog) { 
    // Deleting previous incarnation of the dialog 
    if ($dialog) { 
     $dialog.remove(); 
    } 
    return $(
     '<div id="waitingFor" class="modal fade" data-backdrop="static" data-keyboard="false" tabindex="-1" role="dialog" aria-hidden="true" style="padding-top:15%; overflow-y:visible;">' + 
      '<div class="modal-dialog modal-m">' + 
       '<div class="modal-content">' + 
        '<div class="modal-header" style="display: none;"></div>' + 
        '<div class="modal-body">' + 
         '<div class="progress progress-striped active" style="margin-bottom:0;">' + 
          '<div class="progress-bar" style="width: 100%"></div>' + 
         '</div>' + 
        '</div>' + 
       '</div>' + 
      '</div>' + 
     '</div>' 
    ); 
} 

// Dialog object 
var $dialog; 

return { 
    /** 
    * Opens our dialog 
    * @param message Custom message 
    * @param options Custom options: 
    * options.headerText - if the option is set to boolean false, 
    *  it will hide the header and "message" will be set in a paragraph above the progress bar. 
    *  When headerText is a not-empty string, "message" becomes a content 
    *  above the progress bar and headerText string will be set as a text inside the H3; 
    * options.headerSize - this will generate a heading corresponding to the size number. Like <h1>, <h2>, <h3> etc; 
    * options.headerClass - extra class(es) for the header tag; 
    * options.dialogSize - bootstrap postfix for dialog size, e.g. "sm", "m"; 
    * options.progressType - bootstrap postfix for progress bar type, e.g. "success", "warning"; 
    * options.contentElement - determines the tag of the content element. 
    *  Defaults to "p", which will generate a <p> tag; 
    * options.contentClass - extra class(es) for the content tag. 
    */ 
    show: function (message, options) { 
     // Assigning defaults 
     if (typeof options === 'undefined') { 
      options = {}; 
     } 
     if (typeof message === 'undefined') { 
      message = 'Loading'; 
     } 
     var settings = $.extend({ 
      headerText: '', 
      headerSize: 3, 
      headerClass: '', 
      dialogSize: 'm', 
      progressType: '', 
      contentElement: 'p', 
      contentClass: 'content', 
      onHide: null // This callback runs after the dialog was hidden 
     }, options), 
     $headerTag, $contentTag; 

     $dialog = constructDialog($dialog); 

     // Configuring dialog 
     $dialog.find('.modal-dialog').attr('class', 'modal-dialog').addClass('modal-' + settings.dialogSize); 
     $dialog.find('.progress-bar').attr('class', 'progress-bar'); 
     if (settings.progressType) { 
      $dialog.find('.progress-bar').addClass('progress-bar-' + settings.progressType); 
     } 

     // Generate header tag 
     $headerTag = $('<h' + settings.headerSize + ' />'); 
     $headerTag.css({ 'margin': 0 }); 
     if (settings.headerClass) { 
      $headerTag.addClass(settings.headerClass); 
     } 

     // Generate content tag 
     $contentTag = $('<' + settings.contentElement + ' />'); 
     if (settings.contentClass) { 
      $contentTag.addClass(settings.contentClass); 
     } 

     if (settings.headerText === false) { 
      $contentTag.html(message); 
      $dialog.find('.modal-body').prepend($contentTag); 
     } 
     else if (settings.headerText) { 
      $headerTag.html(settings.headerText); 
      $dialog.find('.modal-header').html($headerTag).show(); 

      $contentTag.html(message); 
      $dialog.find('.modal-body').prepend($contentTag); 
     } 
     else { 
      $headerTag.html(message); 
      $dialog.find('.modal-header').html($headerTag).show(); 
     } 

     // Adding callbacks 
     if (typeof settings.onHide === 'function') { 
      $dialog.off('hidden.bs.modal').on('hidden.bs.modal', function() { 
       settings.onHide.call($dialog); 
      }); 
     } 
     // Opening dialog 
     $dialog.modal(); 
    }, 
    /** 
    * Closes dialog 
*/ 
    hide: function() { 
     if (typeof $dialog !== 'undefined') { 
      $dialog.modal('hide'); 
     } 
    } 
}; 
})); 

我使用NPOI以在后面的代码Excel文件米(简化功能):

using NPOI.SS.UserModel; 
using NPOI.XSSF.UserModel; 

protected void exportExcel() 
{ 
    XSSFWorkbook wb = new XSSFWorkbook(); 

    XSSFSheet sh = (XSSFSheet)wb.CreateSheet("Legend"); 

    //***************************************** 
    //* Workbook Download & Cleanup 
    //***************************************** 
    MemoryStream stream = new MemoryStream(); 
    wb.Write(stream); 
    stream.Dispose(); 

    var xlsBytes = stream.ToArray(); 
    string filename = "Behavior Stats YTD.xlsx"; 

    MemoryStream newStream = new MemoryStream(xlsBytes); 

    HttpContext.Current.Response.ContentType = "application/octet-stream"; 
    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8; 
    HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + filename); 
    HttpContext.Current.Response.BinaryWrite(xlsBytes); 
    HttpContext.Current.Response.Flush(); 
    HttpContext.Current.Response.End(); 
} 

此创建Excel文件并将其推给用户,但是代码的生命周期的后面不续inue - 在结束命令后立即停止。如果我注释掉HttpContext行,显然Excel表格不会被创建,但页面的生命周期仍在继续 - 其余的代码运行,页面刷新,并且模式Please Wait对话框消失。

那么我使用这个错误?我见过的大多数例子都是用这种方法导出的。我还有另一种更清洁和/或更安全的出口方式吗?我需要做一个简单的调整,这将让生命周期继续下去吗?谁创造了液体肥皂,为什么?

任何帮助你可以提供将大大,非常感谢。

回答

0

它的工作原理应该完全相同。您正在告诉浏览器该响应是一个文件。回应一次只能是一件事。您不能在同一个响应中包含页面内容和文件。

您可以通过在IFrame中下载文件来分开两者。首先把你的文件下载C#代码在它自己的页面中。然后使用JavaScript函数从IFrame调用该页面。

function DownloadExcel() { 
    var downloadFrame = document.createElement("IFRAME"); 

    if (downloadFrame != null) { 
     downloadFrame.setAttribute("src", '/DownloadExcel.aspx'); 
     downloadFrame.style.width = "0px"; 
     downloadFrame.style.height = "0px"; 
     document.body.appendChild(downloadFrame); 
    } 
} 
+0

我真诚地不能谢谢你,这已经让我头痛的时间最长,你的解决方案也简单而优雅。我也很欣赏对这个回应是什么的解释 - 出于某种原因,这只是让我的脑海里“点击”的东西,并且我明白了它为什么不起作用。再次感谢和快乐编码! –

+0

不客气。乐于帮助! –