2016-05-12 261 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

不客氣。樂於幫助! –