2011-12-05 30 views
6

Necesito renderizar una página HTML del lado del servidor y "extraer" los bytes brutos de un elemento canvas para poder guardarlo en un archivo PNG. El problema es que el elemento canvas se crea desde javascript (estoy usando Flot de jquery para generar un gráfico, básicamente). Así que supongo que necesito una forma de "alojar" la funcionalidad DOM + Javascript desde un navegador sin utilizar realmente el navegador. Me decidí por mshtml (pero estoy abierto a todas las sugerencias) ya que parece que debería ser capaz de hacerlo exactamente. Este es un proyecto ASP.NET MVC.Rendering HTML + Javascript del lado del servidor

He buscado a lo largo y ancho y no he visto nada concluyente.

así que tengo este sencillo HTML - ejemplo mantiene tan simple como sea posible para demostrar el problema -

<!DOCTYPE html> 
<html> 
<head> 
    <title>Wow</title> 
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js" type="text/javascript"></script> 
</head> 
<body> 
    <div id="hello"> 
    </div> 
    <script type="text/javascript"> 
     function simple() 
     { 
      $("#hello").append("<p>Hello</p>"); 
     }      
    </script> 
</body> 
</html> 

que produce el resultado esperado cuando se ejecuta desde un navegador.

Quiero ser capaz de cargar el HTML original en la memoria, ejecutar la función javascript y luego manipular el árbol DOM final. No puedo usar ninguna clase similar a System.Windows.WebBrowser, ya que mi código debe ejecutarse en un entorno de servicio.

Así que aquí es mi código:

IHTMLDocument2 domRoot = (IHTMLDocument2)new HTMLDocument(); 

     using (WebClient wc = new WebClient()) 
     { 
      using (var stream = new StreamReader(wc.OpenRead((string)url))) 
      { 
       string html = stream.ReadToEnd(); 
       domRoot.write(html); 
       domRoot.close(); 
      } 
     } 

     while (domRoot.readyState != "complete") 
      Thread.Sleep(SleepTime); 

     string beforeScript = domRoot.body.outerHTML; 

     IHTMLWindow2 parentWin = domRoot.parentWindow;    
     parentWin.execScript("simple"); 

     while (domRoot.readyState != "complete") 
      Thread.Sleep(SleepTime); 


     string afterScript = domRoot.body.outerHTML; 

     System.Runtime.InteropServices.Marshal.FinalReleaseComObject(domRoot); 
     domRoot = null; 

El problema es, "beforeScript" y "afterScript" son exactamente lo mismo. La instancia de IHTMLDocument2 pasa por el ciclo normal "no inicializado", "cargando", "completo", no se generan errores, nada.

¿Alguien tiene alguna idea sobre lo que estoy haciendo mal? Completamente perdido aquí.

Respuesta

1

He encontrado Awesomium ¿El exactamente lo que necesito! "Marco de navegador web sin ventanas". Brillante.

1

Básicamente estás tratando de hacer cosas que no están destinadas a ser hechas de esa manera.

Genera HTML + Javascript para permitir que el navegador lo dibuje. Escribe C# para habilitar cualquier tipo de cosas del lado del servidor.

Generar HTML + Javascript en el servidor para cargarlo en un navegador en el servidor para poder guardar PNG suena mal.

¿Pensó en otros enfoques, como generar la imagen utilizando el componente C# del lado del servidor? Básicamente, ¿por qué realmente necesitas guardarlo en el servidor? Tal vez alguien puede proporcionar una mejor solución?

+0

Gracias por tomarse el tiempo para responder, pero no estarán de acuerdo con lo que ha dicho - con respecto a "no pretende ". El área visible de un navegador (la ventana) debe estar (y está) separada de su motor DOM/Javascript interno. ¿Por qué debería importar dónde se representa el resultado? ¿Por qué no se puede representar el DOM + CSS + Javascript en cualquier ubicación de la memoria? De hecho, hay un ejemplo de interacción de Node.js con Flot para hacer exactamente lo que quiero hacer: generar un servidor gráfico. Lamentablemente, no puedo usar Node.js ... –

+0

En cuanto a lo que tengo que hacer en el servidor, necesito, periódicamente, producir un gráfico (por ahora, usando Flot) en un entorno sin cabeza, no interactivo. El gráfico debe verse exactamente igual que si un usuario estuviera viendo la página web en un navegador. Este es un proyecto ASP.NET MVC, no he encontrado ningún control/componente del lado del servidor para hacer esto fácilmente. –

+0

Sí, básicamente tienes razón. Realmente tiene sentido renderizar DOM + CSS + Javascript en cualquier parte de la memoria. Sin embargo, esperaría que esto funcione con un navegador, que no se puede cargar en una sesión no interactiva. De todos modos, te deseo buena suerte, si continúas con esto. –

Cuestiones relacionadas