2012-08-23 41 views
2

我有一個將Excel作爲自定義FileResult返回的操作。我的解決方案基於ClosedXml庫(內部使用OpenXml)。 我的XlsxResult類使用服務器上的只讀.xlsx文件作爲模板。然後它將模板傳遞到一個內存流中,然後使用ClosedXml進行操作並保存。最後,將內存流寫入響應。Azure上的自定義FileResult:瀏覽器永遠等待

這對卡西尼以及IIS Express都可以正常工作,但在部署在天藍色時無法正常工作,無任何錯誤。我遇到的唯一影響是發送到服務器的請求永遠不會得到任何迴應。我仍然在等待的東西到60分鐘左右後發生......

我的行動:

[OutputCache(Location= System.Web.UI.OutputCacheLocation.None, Duration=0)] 
public FileResult Export(int year, int month, int day) { 
    var date = new DateTime(year, month, day); 
    var filename = string.Format("MyTemplate_{0:yyyyMMdd}.xlsx", date); 

    //return new FilePathResult("~/Content/templates/MyTemplate.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 

    var result = new XlsxExportTemplatedResult("MyTemplate.xlsx", filename, (workbook) => { 
      var ws = workbook.Worksheets.Worksheet("My Export Sheet"); 
      ws.Cell("B3").Value = date; 
      // Using a OpenXML's predefined formats (15 stands for date) 
      ws.Cell("B3").Style.NumberFormat.NumberFormatId = 15; 
      ws.Columns().AdjustToContents(); // You can also specify the range of columns to adjust, e.g. 
      return workbook; 
     }); 
    return result; 
} 

我FileResult

public class XlsxExportTemplatedResult : FileResult 
{ 
    // default buffer size as defined in BufferedStream type 
    private const int BufferSize = 0x1000; 

    public static readonly string TEMPLATE_FOLDER_LOCATION = @"~\Content\templates"; 

    public XlsxExportTemplatedResult(string templateName, string fileDownloadName, Func<XLWorkbook, XLWorkbook> generate) 
     : base("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { 
     this.TempalteName = templateName; 
     this.FileDownloadName = fileDownloadName; 
     this.Generate = generate; 
    } 

    public string TempalteName { get; protected set; } 
    public Func<XLWorkbook, XLWorkbook> Generate { get; protected set; } 

    protected string templatePath = string.Empty; 
    public override void ExecuteResult(ControllerContext context) { 
     templatePath = context.HttpContext.Server.MapPath(System.IO.Path.Combine(TEMPLATE_FOLDER_LOCATION, this.TempalteName)); 
     base.ExecuteResult(context); 
    } 

    //http://msdn.microsoft.com/en-us/library/office/ee945362(v=office.11).aspx 
    protected override void WriteFile(System.Web.HttpResponseBase response) { 
     FileStream fileStream = new FileStream(templatePath, FileMode.Open, FileAccess.Read); 
     using (MemoryStream memoryStream = new MemoryStream()) { 
      CopyStream(fileStream, memoryStream); 
      using (var workbook = new XLWorkbook(memoryStream)) { 
       Generate(workbook); 
       workbook.Save(); 
      } 
      // At this point, the memory stream contains the modified document. 
      // grab chunks of data and write to the output stream 
      Stream outputStream = response.OutputStream; 
      byte[] buffer = new byte[BufferSize]; 
      while (true) { 
       int bytesRead = memoryStream.Read(buffer, 0, BufferSize); 
       if (bytesRead == 0) { 
        // no more data 
        break; 
       } 
       outputStream.Write(buffer, 0, bytesRead); 
      } 
     } 
     fileStream.Dispose(); 
    } 

    static private void CopyStream(Stream source, Stream destination) { 
     byte[] buffer = new byte[BufferSize]; 
     int bytesRead; 
     do { 
      bytesRead = source.Read(buffer, 0, buffer.Length); 
      destination.Write(buffer, 0, bytesRead); 
     } while (bytesRead != 0); 
    } 

} 

所以我失去的東西(顯然我是)。

請注意:

  1. 沒有dll文件,因爲我查了使用Windows Azure工具1.7
  2. 我的出口是不是一個沉重的長期運行的任務的遠程訪問功能可以從Azure中失蹤。
  3. 當我將操作更改爲僅返回帶有模板xlsx的FilePathResult時,它在azure上工作。但我需要在返回之前處理文件,因爲你可能會懷疑:-)

坦克。

UPDATE: 後,我在我的代碼登錄廣泛的執行與在ClosedXml「保存」方法調用沒有錯誤掛起。但仍然沒有錯誤。從路徑

  • 打開模板文件: E:從WADLogsTable摘要\ sitesroot \ 0 \內容\模板\ MyTemplate.xlsx
  • 從路徑
  • 打開模板: E:\ sitesroot \ 0 \內容\模板\ MyTemplate.xlsx只需
  • 將模板複製到可編輯內存流。字節複製:15955, 位置:15955
  • 修改了內存中的excel文件。
  • 這裏它掛起時,它調用workbook.Save();這是一個ClosedXml方法調用。
+1

如果您沒有收到任何錯誤,我們不會輕易爲您提供幫助。嘗試在每行代碼之間添加一些日誌記錄。通過這種方式,您可以確切知道「停止」處理請求的位置,我們將更好地瞭解發生了什麼。 –

+0

@SandrinoDiMattia我會嘗試記錄跟蹤並返回更多信息。但奇怪的是,當我遠程訪問Azure實例之一時,沒有在EventLog中發生異常的條目。 – cleftheris

+0

@SandrinoDiMattia我更新了更多信息的問題。這似乎是我正在使用的ClosedXml庫問題。我下載了源代碼。 +1給你的評論,因爲我覺得我在某處:-) – cleftheris

回答

1

我正面臨與您完全相同的錯誤情況。我無法解決您的具體情況,並且我知道您切換了曲目,但在經歷了您遇到的同樣令人沮喪的步驟之後,我想爲您(或其他人)的答案「鋪平道路」 。

拖放到Visual Studio中的包管理器控制檯,並與MVC東西(路由)安裝ELMAH:現在

Install-Package elmah.MVC 

,在你的根web.config中,更新ELMAH條目。很可能在文件的結尾,看起來像這樣:

<elmah></elmah> 

更新壞小子允許遠程訪問並設置日誌路徑:

<elmah> 
     <security allowRemoteAccess="1" /> 
     <errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/app_data/elmah" /> 
    </elmah> 

現在,把多達Azure上。

最後,訪問您的網站,強制執行錯誤,然後導航至http://your-site-here.azurewebsites.net/elmah,您將看到錯誤的確切原因。

Elmah太棒了。

羞怯自白:爲我的錯誤是不是在第三方代碼,它竟然在我的連接字符串,爲此,我還沒有設置MultipleActiveResultsSets爲true。我必須做的另一個解決方案是在將ToList()傳遞給該庫中的某個內部方法之後,將其中的實體傳遞給該庫,並將其保留爲IQueryable。

+0

感謝您的回答。 +1建議elmah夢幻般的圖書館!不幸的是,當你在我的情況中看到我的問題時,爲了在切換到EPPlus之前將我的代碼劃分爲無sql的代碼。 – cleftheris