2012-04-25 4 views
1

こんにちはiFrameとボタンを持つウェブサイトを作成しています。そのボタンの機能は、iFrame内に表示されているもののスクリーンショットを取得して、 harddisk.Belowは私がボタンをクリックするとiFrameのスクリーンショットを撮る

private void saveURLToImage(string url) 
    { 
     if (!string.IsNullOrEmpty(url)) 
     { 
      string content = ""; 


      System.Net.WebRequest webRequest = WebRequest.Create(url); 
      System.Net.WebResponse webResponse = webRequest.GetResponse(); 
      System.IO.StreamReader sr = new StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.GetEncoding("UTF-8")); 

      content = sr.ReadToEnd(); 
      //save to file 
      byte[] b = Convert.FromBase64String(content); 
      System.IO.MemoryStream ms = new System.IO.MemoryStream(b); 
      System.Drawing.Image img = System.Drawing.Image.FromStream(ms); 
      img.Save(@"c:\pic.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); 


      img.Dispose(); 
      ms.Close(); 
     } 
    } 

を使用していたコードであり、ここで、私はエラー

に取得しています]ボタンをクリックしたときにボタンのコードは、しかし

protected void Button1_Click(object sender, ImageClickEventArgs e) 
{ 

saveURLToImage("http://www.google.com"); 

} 

をクリックしています10私はit.Any助けを解決する方法を見つけ出すことができません。このライン

byte[] b = Convert.FromBase64String(content); 

が大幅contentがページを作る生のHTMLであるあなたのケースでは、あなたに

答えて

4

をappreciated.Thankされるだろうどのようにレンダリングされているのではなく、それはbase 64(これはASCII文字を使ってバイナリデータをエンコードする方法)ではないので、ブラウザに決定する(デバッガで見てください)ようになります。これを動作させるには、JPEGエンコードされた画像のベース64エンコードバイナリデータを取得する必要がありますが、ブラウザはHTMLをレンダリングしています。持っている。

これは、Webアプリケーションで実現するのは簡単ではないと思います.Netコードでは、サーバー上で実行されているため、HTMLをレンダリングしてスクリーンショットを撮ることがクライアントの仕事ですの。あなたは可能性があります(そして、これはおそらく本当に壊れやすいので、私は実際にそれを推奨しません、Webアプリケーションでこのようなwinformsコントロールをホストすることは、通常はトラブルのレシピですが、可能かもしれないと思います)browser controlをサーバー側で使用してくださいそのURLを設定しますが、何らかのスクリーンショットが必要な場合は、Taking Website Screenshots With The WebBrowser Controlが役に立ちます。ウェブサイトのコメントで離れて隠れ

更新

私は最後にリンクされ、実際に(WebBrowserコントロールを使用して)ウェブページのスクリーンショットを取るために働くいくつかのコードです。

  • のMicrosoft HTMLオブジェクトライブラリ
  • (これはCOMの参照ではなく、.NET一つです)
  • のSystem.Windows.Forms

    • System.Drawing:それはあなたが次への参照を持っていることが必要ですここで

      私たちが望む仕事をしていませんクラスが(ウリとサイズを取り、ビットマップを返し、その上に1つだけRenderメソッドを持っている)である。

      using System; 
      using System.Drawing; 
      using System.Runtime.InteropServices; 
      using System.Threading; 
      using System.Windows.Forms; 
      using mshtml; 
      
      public class HtmlToBitmapConverter 
      { 
          public Bitmap Render(Uri uri, Size size) 
          { 
           var browser = new WebBrowser 
                { 
                 ScrollBarsEnabled = false, 
                 ScriptErrorsSuppressed = true, 
                 Size = size 
                }; 
           browser.BringToFront(); 
      
           NavigateAndWaitForLoad(browser, uri, 0); 
      
           var bitmap = new Bitmap(size.Width, size.Height); 
           GetImage(browser.Document.DomDocument, bitmap, Color.White); 
           return bitmap; 
          } 
      
          private void NavigateAndWaitForLoad(WebBrowser browser, 
                   Uri uri, 
                   int waitTime) 
          { 
           const int sleepTimeMiliseconds = 5000; 
      
           browser.Navigate(uri); 
           var count = 0; 
      
           while (browser.ReadyState != WebBrowserReadyState.Complete) 
           { 
            Thread.Sleep(sleepTimeMiliseconds); 
            Application.DoEvents(); 
            count++; 
      
            if (count > waitTime/sleepTimeMiliseconds) 
            { 
             break; 
            } 
           } 
      
           while (browser.Document.Body == null) 
           { 
            Application.DoEvents(); 
           } 
      
           var document = (IHTMLDocument2)browser.Document.DomDocument; 
           var style = (IHTMLStyle2)document.body.style; 
           style.overflowX = "hidden"; 
           style.overflowY = "hidden"; 
          } 
      
          private static void GetImage(object obj, 
                 Image destination, 
                 Color backgroundColor) 
          { 
           using (var graphics = Graphics.FromImage(destination)) 
           { 
            var deviceContextHandle = IntPtr.Zero; 
            var rectangle = new Rect 
            { 
             Right = destination.Width, 
             Bottom = destination.Height 
            }; 
      
            graphics.Clear(backgroundColor); 
            try 
            { 
             deviceContextHandle = graphics.GetHdc(); 
      
             var viewObject = (IViewObject)obj; 
             viewObject.Draw(1, 
                 -1, 
                 IntPtr.Zero, 
                 IntPtr.Zero, 
                 IntPtr.Zero, 
                 deviceContextHandle, 
                 ref rectangle, 
                 IntPtr.Zero, 
                 IntPtr.Zero, 
                 0); 
            } 
            finally 
            { 
             if (deviceContextHandle != IntPtr.Zero) 
             { 
              graphics.ReleaseHdc(deviceContextHandle); 
             } 
            } 
           } 
          } 
      
          [ComImport] 
          [Guid("0000010D-0000-0000-C000-000000000046")] 
          [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
          private interface IViewObject 
          { 
           void Draw([MarshalAs(UnmanagedType.U4)] uint dwAspect, 
              int lindex, 
              IntPtr pvAspect, 
              [In] IntPtr ptd, 
              IntPtr hdcTargetDev, 
              IntPtr hdcDraw, 
              [MarshalAs(UnmanagedType.Struct)] ref Rect lprcBounds, 
              [In] IntPtr lprcWBounds, 
              IntPtr pfnContinue, 
              [MarshalAs(UnmanagedType.U4)] uint dwContinue); 
          } 
      
          [StructLayout(LayoutKind.Sequential, Pack = 4)] 
          public struct Rect 
          { 
           public int Left; 
      
           public int Top; 
      
           public int Right; 
      
           public int Bottom; 
          } 
      } 
      

      NOTE私は、私はこれが理由のカップルのためのWebアプリケーションで使用するための素晴らしいアイデアであることを確認していない前に言ったように:

      1. これは、Windowsフォームがそう、それはを扱う方法を制御していますメモリがWebアプリケーションで使用されることと互換性がない可能性があります。
      2. これは、スクリーンショットを取っているアカウントは、Webアプリケーションが実行されているアカウントであり、必ずしもエンドユーザーではありません。

      OK、私は

      私は...ねえ、私たちはそれをここに、とにかく動作させることができ、上記のWinFormsアプリで罰金が、ウェブのための、おそらく適切ではないだろうと思いますが、あなたは.aspxページにこのようなものを持っているでしょう。その場合には、通常のASP .NET Webアプリケーションのために行くされていると仮定すると:

      <asp:Button runat="server" OnClick="TakeScreenShot" Text="Take Screenshot"/> 
      

      その後TakeScreenshot方法の背後にあるコードでは次のようになります。

      protected void TakeScreenShot(object sender, EventArgs e) 
      { 
          Uri uri = new Uri("http://www.google.com"); 
      
          // Because it is a WebBrowser control it needs to run in an STA 
          // thread - what we will do is render the image to a Bitmap then 
          // store the raw bytes in this byte array from a newly created 
          // thread 
          byte[] screenshot = null; 
          var t = new Thread(() => 
                { 
                 using (var ms = new MemoryStream()) 
                 { 
                  // The screenshot object contains a 640x480 
                  // screenshot 
                  var bitmap = new HtmlToBitmapConverter() 
                   .Render(uri, 
                     new Size(640, 480)); 
                  bitmap.Save(ms, ImageFormat.Jpeg); 
                  screenshot = ms.ToArray(); 
                 } 
                }); 
          t.SetApartmentState(ApartmentState.STA); 
          t.Start(); 
          t.Join();    
      
          // Here we have the JPEG encoded bytes of the image - we can 
          // just save them to a file like so... 
          using (var f = File.Create(@"c:\google.jpg")) 
          { 
           f.Write(screenshot, 0, screenshot.Length); 
          } 
      } 
      

      あなたが行く - c:\ google.jpgにはGoogleのスクリーンショットがあります。

  • +0

    私のiframeにはpentaho.Alsoからのレポートが含まれています。以前に指定した方法を使用しましたが、空白の写真が表示されます。多くのスクリーンショットテクニックを試しましたが、機能しません。私のiframe内のコンテンツのスクリーンショットを撮る。 – nitinvertigo

    +0

    @nitinvertigo実際の作業の解決策は、その記事のコメントにあります(記事のコードが実際に動作するかどうかはわかりません - これを行う方法については、Web上に多くのことがあるようです)。私はそれを簡略化し、この答えを更新しました。私もaspからそれを呼び出す方法を示しています.net webformsアプリケーション – kmp

    +0

    ありがとうございました。あなたのコードは完璧に動作します:)私は大丈夫です:) :) – nitinvertigo