2017-03-28 46 views
0

在我的MVC應用程序中,我在STA線程中使用Web瀏覽器控件。我想在STA線程結束時向客戶端發送一個png圖像。在MVC中使用sta線程下載png圖像

這是我的代碼

  public void Export() //Action method for exporting 
     { 
      //Saving widget as image using web browser control 
      System.Threading.Thread tr = new System.Threading.Thread(() => ExportWidget()); 
      tr.SetApartmentState(ApartmentState.STA); 
      tr.Start(); 
     } 

     public void ExportWidget() //STA method for downloading 
     { 

      WebBrowser browser = new WebBrowser() { ScriptErrorsSuppressed=true, WebBrowserShortcutsEnabled = false, Size = new System.Drawing.Size(1000, 1000) }; 

      browser.DocumentText = new StringBuilder() 
       //Add header for HTML document 
       .Append("<!DOCTYPE html><html><head><meta http-equiv='X-UA-Compatible' content='IE=edge' />" 

       //Add scripts required for rendering widget in browser control 
       + AddScripts(browser, widgetOption) 

       + "</head><body><div id='widgetContainer'></div></body></html>").ToString(); 


      //Check browser is loaded or not. If it is not ready wait until browser loading is complete 
      while (browser.ReadyState == WebBrowserReadyState.Loading) 
      { 
       Application.DoEvents(); 
       Thread.Sleep(5); 
      } 

      MemoryStream stream = new MemoryStream(); 

      using (Bitmap img = new Bitmap(ParseInt(bounds[1]), ParseInt(bounds[0]))) 
      { 
       browser.DrawToBitmap(img, new Rectangle(ParseInt(bounds[2]), ParseInt(bounds[3]), img.Width, img.Height));   
       img.Save(stream, ImageFormat.Png); 

       browser.Dispose();     
      } 

      Response.Clear(); 

      stream.WriteTo(Response.OutputStream); 
      stream.Dispose(); 
      string fileName = "WidgetExport.png"; 
      Response.ContentType = "application/octet-stream"; 

      //System.ArgumentException throws here 
      Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName); 
      Response.Flush(); 
     } 

我檢查出口在服務器端的一個JavaScript小部件的可能性。

這是正確的方法嗎?上面的代碼頭設置在「內容處置」

請分享您的建議

回答

0

幾個小時後分析拋出System.ArgumentException,我想出了以下解決方案,在服務器 - 完全下載一個JavaScript控件側。

這是不優雅,但目前這是我所知道的唯一的解決方案,工程

  public void Export() //Action method for exporting 
     { 
      //Saving widget as image using web browser control 
      System.Threading.Thread tr = new System.Threading.Thread(() => ExportWidget()); 
      tr.SetApartmentState(ApartmentState.STA); 
      tr.Start(); 

      string fileName = Server.MapPath(@"\WidgetExport.png");    

      //Make current thread waits until widget image is ready in STA thread 
      while(tr.IsAlive) 
      { 
       Thread.Sleep(5); 
      } 

      //Read widget image as bytes 
      byte[] file = System.IO.File.ReadAllBytes(fileName); 

      //Delete the file after reading 
      System.IO.File.Delete(fileName); 

      //Allowing client to download the image 
      Response.OutputStream.Write(file, 0, file.Length); 
      Response.ContentType = "application/octet-stream";    
      Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName); 
      Response.Flush(); 
     } 

    public void ExportWidget() //STA thread method for downloading 
    { 

     WebBrowser browser = new WebBrowser() { ScriptErrorsSuppressed=true, WebBrowserShortcutsEnabled = false, Size = new System.Drawing.Size(1000, 1000) }; 

     browser.DocumentText = new StringBuilder() 
      //Add header for HTML document 
      .Append("<!DOCTYPE html><html><head><meta http-equiv='X-UA-Compatible' content='IE=edge' />" 

      //Add scripts required for rendering widget in browser control 
      + AddScripts(browser, widgetOption) 

      + "</head><body><div id='widgetContainer'></div></body></html>").ToString(); 


     //Check browser is loaded or not. If it is not ready wait until browser loading is complete 
     while (browser.ReadyState == WebBrowserReadyState.Loading) 
     { 
      Application.DoEvents(); 
      Thread.Sleep(5); 
     } 

     MemoryStream stream = new MemoryStream(); 

     using (Bitmap img = new Bitmap(ParseInt(bounds[1]), ParseInt(bounds[0]))) 
     { 
      browser.DrawToBitmap(img, new Rectangle(ParseInt(bounds[2]), ParseInt(bounds[3]), img.Width, img.Height));   
      img.Save(Server.MapPath(@"\WidgetExport.png"), ImageFormat.Png); 

      browser.Dispose();     
     } 
    } 

上面的代碼執行以下操作

  1. 客戶端請求到達服務器

  2. Server填充JavaScript小部件使用C#封裝器

  3. WebBrowser控件在操作方法的線程中不起作用,因爲它只在STA線程中起作用。應該停止動作方法的線程直到STA線程完成

  4. 因此,啓動一個新的STA線程並在其中創建WebBrowser控件。

  5. 添加在WebBrowser控件的窗口小部件

  6. 序列化的C#包裝等效JavaScript作爲字符串,並將其添加到WebBrowser控件

  7. 使用執行序列化的JavaScript代碼所需的HTML內容和腳本WebBrowser控件的InvokeScript方法。這會使得小部件WebBrowser控件WebBrowser控件的

  8. 使用DrawToBitmap方法繪製的JavaScript控件的圖像中的位圖

  9. 保存和處理位圖。配置WebBrowser控件。 STA線程的執行現在完成

  10. 現在應該使用線程操作方法。您可以通過小工具圖像,其保存在STA線程

  11. 刪除服務器中的圖像數據讀取數據後

  12. 允許圖像在客戶端使用Response.OutputStream

下載