2017-03-28 23 views
0

MVCアプリケーションでは、STAスレッドでWebブラウザコントロールを使用しています。私は、STAスレッドの最後にクライアントにpngイメージを送信したいと思います。MVCのstaスレッドを使用してpngイメージをダウンロード

これは、私は、サーバー側で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(); 
     } 

     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(); 
     } 

です。

これは正しい方法ですか?上記のコードSystem.ArgumentExceptionのは、ヘッダ

での「Content-処分」を設定する際に数時間のために分析した後、あなたの提案

答えて

0

を共有してください、私は完全にサーバ - の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が移入C#ラッパーを使用したJavaScriptウィジェット

  3. WebBrowserコントロールは、STAスレッドでのみ機能するため、アクションメソッドのスレッドでは機能しません。アクションスレッドのメソッドは、STAスレッドが完了するまで停止する必要があります。

  4. したがって、新しいSTAスレッドを開始し、そこにWebBrowserコントロールを作成します。

  5. WebBrowserコントロールでウィジェットに必要なHTMLコンテンツおよびスクリプトを追加

  6. 使用してシリアル化されたJavaScriptコードを実行し、文字列として同等のJavaScriptのC#ラッパーをシリアル化し、WebBrowserコントロールに

  7. をそれを追加WebBrowserコントロールのInvokeScriptメソッド。これは、ビットマップ

  8. 保存でJavaScriptウィジェットの画像を描画し、ビットマップを配置するWebBrowserコントロールにWebBrowserコントロールの

  9. 使用DrawToBitmapメソッドをウィジェットをレンダリングします。 Webブラウザーコントロールを破棄します。 STAスレッドの実行が完了しました

  10. アクションメソッドのスレッドが利用可能になるはずです。

  11. 画像が

Response.OutputStream

使用してクライアントにダウンロードすることができるようにデータを読み込んだ後にSTAスレッド

  • サーバから画像を削除して保存したウィジェット画像からデータを取得します。

  • 関連する問題