1. 安装Graphviz 2.28, 安装目录不要修改,C:\Program Files\Graphviz 2.28\bin\dot.exe;
2. 在Web.config中,添加节点:
- <appSettings>
- <!-- Graphviz 执行文件路径 -->
- <add key="dotExePath" value="C:\Program Files\Graphviz 2.28\bin\dot.exe" />
- </appSettings>
3. 建立帮助类
- using System;
- using System.Collections.Generic;
- using System.Text.RegularExpressions;
- using System.Web;
- using System.IO;
- using System.Diagnostics;
- using System.Text;
- using System.Net;
- using System.Drawing.Imaging;
- using System.Drawing;
- namespace Module.Common
- {
- /// <summary>
- /// 拓扑图
- /// </summary>
- public class GraphvizHelper
- {
- public static void SaveWebImgToLocal(string url)
- {
- string path=GetImgSavePath();
- if(path=="" || url.IndexOf('/')== -1 )
- return;
- path += url.Substring(url.LastIndexOf('/'));
- WebClient my=new WebClient();
- byte[] mybyte;
- mybyte=my.DownloadData(url);
- MemoryStream ms = new MemoryStream(mybyte);
- System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
- img.Save(path, ImageFormat.Png); //保存
- switch (Path.GetExtension(path))
- {
- case ".gif":
- img.Save(path, ImageFormat.Gif);
- break;
- case ".jpg":
- case ".jpeg":
- img.Save(path, ImageFormat.Jpeg);
- break;
- case ".png":
- img.Save(path, ImageFormat.Png);
- break;
- case ".icon":
- img.Save(path, ImageFormat.Icon);
- break;
- case ".bmp":
- img.Save(path, ImageFormat.Bmp);
- break;
- default:
- img.Save(path, ImageFormat.Png);
- break;
- }
- img.Dispose();
- ms.Dispose();
- CompressJpeg(path, 64);
- }
- public static void CompressJpeg(string strPath, int intWidth)
- {
- var img = Image.FromFile(strPath); // 如果不是图片会出错。
- if (img.Width <= intWidth)
- {
- img.Dispose();
- return;
- }
- var intHeight = img.Height * intWidth / img.Width;
- // 创建位图及相关联的图形处理工具,在位图上画缩略图
- var thm = new Bitmap(intWidth, intHeight);
- var grp = Graphics.FromImage(thm);
- //设置高质量插值法
- grp.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
- //设置高质量,低速度呈现平滑程度
- grp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
- grp.Clear(System.Drawing.Color.Transparent);//清空画布以透明填充
- grp.DrawImage(img, 0, 0, intWidth, intHeight);
- // 释放占用的图片文件
- img.Dispose();
- grp.Dispose();
- // 保存缩略图
- thm.Save(strPath); // 如果不设置图片质量,可直接保存
- thm.Dispose();
- }
- public static string GetNodeMap(string strData)
- {
- StringBuilder sb = new StringBuilder();
- if (String.IsNullOrEmpty(strData))
- {
- sb.Append("subgraph cluster_app1 {label=应用系统1 app1[image=\"../../images/Topology/app.png\"];}");
- sb.Append("subgraph cluster_vm1 {label=虚拟机1 vm1[image=\"../../images/Topology/vm.png\"];}");
- sb.Append("subgraph cluster_vm2 {label=虚拟机2 vm2[image=\"../../images/Topology/vm.png\"];}");
- sb.Append("subgraph cluster_svr1 {label=服务器1 svr1[image=\"../../images/Topology/svr.png\"];}");
- sb.Append("subgraph cluster_sw1 {label=交换机1 sw1[image=\"../../images/Topology/sw.png\"];}");
- sb.Append("subgraph cluster_tap1 {label=磁带机1 tap1[image=\"../../images/Topology/tape.png\"];}");
- sb.Append("app1 -> vm1 [label=安装于]");
- sb.Append("app1 -> vm2 [label=安装于]");
- sb.Append("vm1 -> svr1 [label=承载于]");
- sb.Append("vm2 -> svr1 [label=承载于]");
- sb.Append("svr1 -> sw1 [label=连接]");
- sb.Append("svr1 -> tap1 [label=连接]");
- }
- else {
- sb.Append(strData);
- }
- //前面一段字符
- StringBuilder sb2 = new StringBuilder();
- sb2.Append("digraph G {\n");
- sb2.Append("compound=true;\n");
- sb2.Append("ranksep=0.5;\n");
- sb2.Append("nodesep=0.5;\n");
- sb2.Append("rankdir=LR;\n");
- sb2.Append("graph [penwidth=0, labelloc=\"b\", fontname=simsun, fontcolor=dodgerblue3, fontsize=10]\n");
- sb2.Append("node [shape=plaintext, label=\"\"]\n");
- sb2.Append("edge [color=brown, fontname=simsun, fontcolor=brown1, fontsize=10, weight=1.2];\n");
- //string dotSource_temp = sb2.ToString() + strData; //sb.ToString();
- string dotSource_temp = sb2.ToString() + sb.ToString();
- string dotFileName_temp = Path.GetRandomFileName();
- string dirPath = GetTempDirPath();
- if (dirPath == "") {
- return "";
- }
- string dotFileName = Path.ChangeExtension(Path.Combine(dirPath , Path.GetFileName(dotFileName_temp)), ".dot");
- string pngFile = Path.ChangeExtension(dotFileName, ".png");
- //string pngFile_temp=
- using (StreamWriter writer = new StreamWriter(dotFileName))
- {
- writer.Write(dotSource_temp);
- }
- string dotExePath_temp = System.Configuration.ConfigurationManager.AppSettings["dotExePath"] as string;
- //调用服务器端exe进程
- ProcessStartInfo info = new ProcessStartInfo()
- {
- FileName = dotExePath_temp,
- WorkingDirectory = Path.GetDirectoryName(dotFileName),
- Arguments = string.Concat("-Tpng -o ", pngFile, " ", dotFileName),
- RedirectStandardInput = false,
- RedirectStandardOutput = false,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true
- };
- try
- {
- using (Process exe = Process.Start(info))
- {
- exe.WaitForExit();
- if (0 == exe.ExitCode)
- {
- System.Web.HttpContext.Current.Response.Write(pngFile);
- }
- else
- {
- string errMsg;
- using (StreamReader stdErr = exe.StandardError)
- {
- errMsg = stdErr.ReadToEnd();
- }
- //System.Web.HttpContext.Current.Response.Write(errMsg);
- }
- }
- }
- catch(Exception ex)
- {
- return "";
- }
- String path="~/TempFile/Graphviz/"+Path.GetFileName(pngFile);
- return path;
- }//---- end of GetNodeMap ----
- /// <summary>
- /// 取得临时文件夹路径
- /// </summary>
- /// <returns></returns>
- private static string GetTempDirPath()
- {
- string path = System.Web.HttpContext.Current.Server.MapPath("~")+"\\TempFile\\Graphviz";
- if (!Function.CreateDir(path))
- {
- return "";
- }
- return path;
- }
- /// <summary>
- /// 取得图片保存路径
- /// </summary>
- /// <returns></returns>
- private static string GetImgSavePath()
- {
- string path = System.Web.HttpContext.Current.Server.MapPath("~") + "\\images\\Topology";
- if (!Function.CreateDir(path))
- {
- return "";
- }
- return path;
- }
- }//end of class
- public class Function
- {
- /// <summary>
- /// 根据目录创建文件夹,如果存在就不创建
- /// </summary>
- /// <param name="path"></param>
- /// <returns></returns>
- public static bool CreateDir(string path)
- {
- bool result = true;
- DirectoryInfo dir = new DirectoryInfo(path);
- //目录不存在
- if (!dir.Exists)
- {
- try
- {
- dir.Create();
- }
- catch (Exception e)
- {
- result = false;
- }
- }
- return result;
- }
- }//end of class
- }//end of namespace
4. 加测试数据
- CREATE TABLE Graph(
- ID CHAR(4) PRIMARY KEY,
- PID CHAR(4) NOT NULL,
- Title NVARCHAR(20) NOT NULL,
- RelationShip NVARCHAR(10) NOT NULL,
- Img VARCHAR(200) NOT NULL
- )
- GO
- --填充数据
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('1000','','应用系统','安装于','../../images/Topology/app.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('2001','1000','虚拟机1','承载于','../../images/Topology/vm.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('2002','1000','虚拟机2','承载于','../../images/Topology/vm.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('2003','1000','虚拟机1','承载于','../../images/Topology/vm.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('3001','2001','服务器1','连接','../../images/Topology/svr.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('3002','2001','服务器2','连接','../../images/Topology/svr.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('3003','2002','服务器3','连接','../../images/Topology/svr.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('4001','3001','交换机1','连接','../../images/Topology/sw.png')
- INSERT INTO Graph(ID,PID,Title,RelationShip,Img) VALUES('4002','3002','磁带机2','连接','../../images/Topology/tape.png')
5. 页面调用:
- <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head runat="server">
- <title>无标题页</title>
- </head>
- <body>
- <form id="form1" runat="server">
- <div>
- <asp:Image ID="Image1" runat="server" />
- </div>
- </form>
- </body>
- </html>
- using System;
- using System.Collections;
- using System.Configuration;
- using System.Data;
- using System.Linq;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.HtmlControls;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Xml.Linq;
- using Module.Common;
- using System.Text;
- public partial class _Default : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!this.IsPostBack) {
- LoadInfo();
- }
- }
- private void LoadInfo()
- {
- string sql = "SELECT * FROM Graph";
- DataTable dt = DBHelper.GetDataTableBySql(sql);
- StringBuilder sb = new StringBuilder();
- if (dt == null || dt.Rows.Count == 0)
- return;
- BuildGraphNodes(sb,dt,"",1,5);
- String imgUrl = GraphvizHelper.GetNodeMap(sb.ToString());
- this.Image1.ImageUrl = imgUrl;
- GraphvizHelper.SaveWebImgToLocal("http://hiphotos.baidu.com/yuangengqiang/pic/item/f9eb16e8007ae310b90e2dc3.jpg");
- }
- private void BuildGraphNodes(StringBuilder sb, DataTable dt, string pid, int depth, int maxDepth)
- {
- if(dt==null || dt.Rows.Count==0 || depth > maxDepth )
- return;
- DataRow[] drArr = dt.Select( String.Format("PID='{0}'",pid) );
- if ( drArr == null || drArr.Length == 0)
- return;
- foreach (DataRow dr in drArr) {
- sb.AppendFormat("subgraph cluster_id{0} {{label=\"{1}\" id{0}[image=\"{2}\"];}}\n",
- dr["ID"] as string, ((dr["Title"] as string)??"").Replace("\"","'"), dr["Img"] as string);
- DataRow[] drSubArr = dt.Select(string.Format("PID='{0}'", dr["ID"] as String));
- if (depth < maxDepth)
- {
- foreach (DataRow drSub in drSubArr)
- {
- sb.AppendFormat("id{0} -> id{1} [label=\"{2}\"]\n", ((dr["ID"] as string) ?? "").Replace("\"", "'"), ((drSub["ID"] as string) ?? "").Replace("\"", "'"), dr["RelationShip"] as string);
- }
- }
- BuildGraphNodes(sb, dt, dr["ID"] as String, depth + 1, maxDepth);
- }
- }
- }