WebReportHtml.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. using FastReport.Export;
  2. using FastReport.Export.Html;
  3. using FastReport.Utils;
  4. using System;
  5. using System.IO;
  6. using System.Text;
  7. using System.Web;
  8. using System.Web.UI;
  9. using System.Web.UI.WebControls;
  10. namespace FastReport.Web
  11. {
  12. public partial class WebReport : WebControl, INamingContainer
  13. {
  14. float _pageWidth;
  15. float _pageHeight;
  16. internal void BeginReport(StringBuilder sb, HttpContext context)
  17. {
  18. sb.AppendLine(string.Format("<div class=\"{0}\" style=\"width:{1};height:{2}\">", Prop.ControlID, Width, Height));
  19. }
  20. internal void GetReportTopToolbar(StringBuilder sb)
  21. {
  22. if (Prop.ShowToolbar)
  23. GetToolbar(sb);
  24. }
  25. internal void GetReportBottomToolbar(StringBuilder sb)
  26. {
  27. if (Prop.ShowBottomToolbar)
  28. GetToolbar(sb);
  29. }
  30. private void GetToolbar(StringBuilder sb)
  31. {
  32. string s = Toolbar.GetHtmlBody();
  33. sb.AppendLine(s);
  34. }
  35. internal void EndReport(StringBuilder sb)
  36. {
  37. sb.AppendLine("</div>");
  38. }
  39. private void ReportProcess(StringBuilder sb, HttpContext context)
  40. {
  41. if (Prop.State == ReportState.Empty)
  42. {
  43. ReportLoad(context);
  44. if (Prop.UnlimitedHeight || Prop.UnlimitedWidth)
  45. {
  46. foreach (Base obj in Report.AllObjects)
  47. {
  48. if (obj is ReportPage)
  49. {
  50. if (Prop.UnlimitedWidth)
  51. (obj as ReportPage).UnlimitedWidth = true;
  52. if (Prop.UnlimitedHeight)
  53. (obj as ReportPage).UnlimitedHeight = true;
  54. }
  55. }
  56. }
  57. ReportRegisterDataAndRunEvent();
  58. if (!Prop.ReportDone)
  59. ReportPrepare();
  60. }
  61. if (Prop.State == ReportState.Forms && sb != null)
  62. ProcessDialogs(sb, context);
  63. if (Prop.State == ReportState.Report)
  64. {
  65. Report.PreparePhase2();
  66. if (Report.PreparedPages != null)
  67. {
  68. Prop.State = ReportState.Done;
  69. }
  70. }
  71. if (Prop.State == ReportState.Done)
  72. {
  73. Prop.TotalPages = Report.PreparedPages.Count;
  74. }
  75. }
  76. private void ReportPrepare()
  77. {
  78. Report.PreparePhase1();
  79. Prop.State = ReportState.Forms;
  80. }
  81. internal void ReportRegisterDataAndRunEvent()
  82. {
  83. #if !FRCORE
  84. Config.ReportSettings.ShowProgress = false;
  85. #endif
  86. this.RegisterData(Report);
  87. this.OnStartReport(EventArgs.Empty);
  88. }
  89. internal void ReportLoad(HttpContext context)
  90. {
  91. Config.WebMode = true;
  92. FastReport.Data.ParameterCollection preParams = new FastReport.Data.ParameterCollection(null);
  93. Report.Parameters.CopyTo(preParams);
  94. if (!String.IsNullOrEmpty(Prop.ReportFile))
  95. {
  96. string fileName = Prop.ReportFile;
  97. if (!WebUtils.IsAbsolutePhysicalPath(fileName))
  98. fileName = context.Request.MapPath(fileName,
  99. Path.GetDirectoryName(context.Request.CurrentExecutionFilePath), true);
  100. if (!File.Exists(fileName))
  101. fileName = context.Request.MapPath(Prop.ReportFile,
  102. Prop.ReportPath, true);
  103. Report.Load(fileName);
  104. }
  105. else if (!String.IsNullOrEmpty(Prop.ReportResourceString))
  106. {
  107. Report.ReportResourceString = Prop.ReportResourceString;
  108. }
  109. foreach (FastReport.Data.Parameter param in preParams)
  110. {
  111. if (param.Value != null)
  112. Report.SetParameterValue(param.Name, param.Value);
  113. }
  114. }
  115. internal void GetReportHTML(StringBuilder sb, HttpContext context)
  116. {
  117. ReportProcess(sb, context);
  118. if (Prop.State == ReportState.Done)
  119. ReportInHtmlAndSave(sb, context);
  120. }
  121. private void ReportInHtmlAndSave(StringBuilder sb, HttpContext context)
  122. {
  123. HTMLExport html = new HTMLExport(true); // webPreview mode
  124. html.CustomDraw += this.CustomDraw;
  125. html.StylePrefix = Prop.ControlID.Substring(0, 6);
  126. html.Init_WebMode();
  127. html.Pictures = Prop.Pictures;
  128. html.EmbedPictures = EmbedPictures;
  129. html.EnableVectorObjects = !WebUtils.IsIE8(context); // don't draw svg barcodes for IE8
  130. html.OnClickTemplate =
  131. //"frRequestServer('" + context.Response.ApplyAppPathModifier(WebUtils.HandlerFileName) + "?previewobject={0}&amp;{1}={2}')";
  132. "frClick('" + context.Response.ApplyAppPathModifier(WebUtils.HandlerFileName) + "', '{0}', '{1}', '{2}')";
  133. html.ReportID = Prop.ControlID;
  134. html.EnableMargins = Prop.EnableMargins;
  135. // calc zoom
  136. CalcHtmlZoom(html);
  137. html.Layers = Layers;
  138. html.PageNumbers = SinglePage ? "" : (Prop.CurrentPage + 1).ToString();
  139. if (Prop.AutoWidth)
  140. html.WidthUnits = HtmlSizeUnits.Percent;
  141. if (Prop.AutoHeight)
  142. html.HeightUnits = HtmlSizeUnits.Percent;
  143. html.WebImagePrefix = String.Concat(context.Response.ApplyAppPathModifier(WebUtils.HandlerFileName), "?", WebUtils.PicsPrefix);
  144. html.SinglePage = SinglePage;
  145. html.CurPage = CurrentPage;
  146. html.Export(Report, (Stream)null);
  147. AddOutlineHtml(sb);
  148. sb.Append("<div class=\"frbody\" style =\"");
  149. if (Layers)
  150. sb.Append("position:relative;z-index:0;");
  151. sb.Append("\">");
  152. // container for html report body
  153. int pageWidth = (int)Math.Ceiling(GetReportPageWidthInPixels() * html.Zoom);
  154. int pageHeight = (int)Math.Ceiling(GetReportPageHeightInPixels() * html.Zoom);
  155. int paddingLeft = (int)Math.Ceiling(Padding.Left * html.Zoom);
  156. int paddingRight = (int)Math.Ceiling(Padding.Right * html.Zoom);
  157. int paddingTop = (int)Math.Ceiling(Padding.Top * html.Zoom);
  158. int paddingBottom = (int)Math.Ceiling(Padding.Bottom * html.Zoom);
  159. sb.Append("<div class=\"frcontainer\" style=\"width:" + pageWidth +
  160. "px;height:" + pageHeight +
  161. "px;padding-left:" + paddingLeft +
  162. "px;padding-right:" + paddingRight +
  163. "px;padding-top:" + paddingTop +
  164. "px;padding-bottom:" + paddingBottom + "px\">");
  165. if (html.Count > 0)
  166. {
  167. if (SinglePage)
  168. {
  169. DoAllHtmlPages(sb, html);
  170. Prop.CurrentPage = 0;
  171. }
  172. else
  173. DoHtmlPage(sb, html, 0);
  174. }
  175. sb.Append("</div>"); // frcontainer
  176. sb.Append("</div>"); // frbody
  177. }
  178. private float GetReportPageWidthInPixels()
  179. {
  180. if(SinglePage)
  181. {
  182. foreach (ReportPage page in Report.Pages)
  183. {
  184. // find maxWidth
  185. if (page.WidthInPixels > _pageWidth)
  186. _pageWidth = page.WidthInPixels;
  187. }
  188. }
  189. else
  190. {
  191. _pageWidth = Report.PreparedPages.GetPageSize(CurrentPage).Width;
  192. }
  193. return _pageWidth;
  194. }
  195. private float GetReportPageHeightInPixels()
  196. {
  197. _pageHeight = 0;
  198. if (SinglePage)
  199. {
  200. for(int i = 0; i < Report.PreparedPages.Count; i++)
  201. {
  202. _pageHeight += Report.PreparedPages.GetPageSize(i).Height;
  203. }
  204. }
  205. else
  206. {
  207. _pageHeight = Report.PreparedPages.GetPageSize(CurrentPage).Height;
  208. }
  209. return _pageHeight;
  210. }
  211. private void CalcHtmlZoom(HTMLExport html)
  212. {
  213. float pageWidth = GetReportPageWidthInPixels() + Padding.Horizontal;
  214. float pageHeight = GetReportPageHeightInPixels() + Padding.Vertical;
  215. int scrollbarWidth = 20;
  216. if (Prop.ZoomMode == ZoomMode.Width)
  217. html.Zoom = (float)Math.Round((this.Width.Value - scrollbarWidth) / pageWidth, 2);
  218. else if (Prop.ZoomMode == ZoomMode.Page)
  219. html.Zoom = (float)Math.Round(Math.Min((float)(this.Width.Value - scrollbarWidth) / pageWidth,
  220. (float)(this.Height.Value -
  221. (Prop.ShowToolbar ? Prop.ToolbarHeight : 0) -
  222. (Prop.ShowBottomToolbar ? Prop.ToolbarHeight : 0) - scrollbarWidth) / pageHeight), 2);
  223. else
  224. html.Zoom = Prop.Zoom;
  225. }
  226. private void DoHtmlPage(StringBuilder sb, HTMLExport html, int pageN)
  227. {
  228. if (html.PreparedPages[pageN].PageText == null)
  229. {
  230. html.PageNumbers = (pageN + 1).ToString();
  231. html.Export(Report, (Stream)null);
  232. }
  233. Prop.CurrentWidth = html.PreparedPages[pageN].Width;
  234. Prop.CurrentHeight = html.PreparedPages[pageN].Height;
  235. if (html.PreparedPages[pageN].CSSText != null
  236. && html.PreparedPages[pageN].PageText != null)
  237. {
  238. sb.Append(html.PreparedPages[pageN].CSSText);
  239. sb.Append(html.PreparedPages[pageN].PageText);
  240. StoreHtmlPictures(html, pageN);
  241. }
  242. }
  243. private void DoAllHtmlPages(StringBuilder sb, HTMLExport html)
  244. {
  245. Prop.CurrentWidth = 0;
  246. Prop.CurrentHeight = 0;
  247. for (int pageN = 0; pageN < html.PreparedPages.Count; pageN++)
  248. {
  249. if (html.PreparedPages[pageN].PageText == null)
  250. {
  251. html.PageNumbers = (pageN + 1).ToString();
  252. html.Export(Report, (Stream)null);
  253. if (html.PreparedPages[pageN].Width > Prop.CurrentWidth)
  254. Prop.CurrentWidth = html.PreparedPages[pageN].Width;
  255. if (html.PreparedPages[pageN].Height > Prop.CurrentHeight)
  256. Prop.CurrentHeight = html.PreparedPages[pageN].Height;
  257. }
  258. if (html.PreparedPages[pageN].CSSText != null
  259. && html.PreparedPages[pageN].PageText != null)
  260. {
  261. sb.Append(html.PreparedPages[pageN].CSSText);
  262. sb.Append(html.PreparedPages[pageN].PageText);
  263. StoreHtmlPictures(html, Layers ? 0 : pageN);
  264. }
  265. }
  266. }
  267. private void StoreHtmlPictures(HTMLExport html, int pageN)
  268. {
  269. WebReportCache cache = new WebReportCache(this.Context);
  270. for (int i = 0; i < html.PreparedPages[pageN].Pictures.Count; i++)
  271. {
  272. try
  273. {
  274. Stream picStream = html.PreparedPages[pageN].Pictures[i];
  275. byte[] image = new byte[picStream.Length];
  276. picStream.Position = 0;
  277. int n = picStream.Read(image, 0, (int)picStream.Length);
  278. string guid = html.PreparedPages[pageN].Guids[i];
  279. cache.PutObject(guid, image);
  280. }
  281. catch
  282. {
  283. //Log.AppendFormat("Error with picture: {0}\n", i.ToString());
  284. }
  285. }
  286. }
  287. private void AddOutlineHtml(StringBuilder sb)
  288. {
  289. if (!ShowOutline)
  290. return;
  291. if (Report == null ||
  292. Report.Engine == null ||
  293. Report.Engine.OutlineXml == null ||
  294. Report.Engine.OutlineXml.Count == 0)
  295. return;
  296. StringBuilder outlineJson = new StringBuilder();
  297. outlineJson.Append("[");
  298. BuildOutline(outlineJson, Report.Engine.OutlineXml, true);
  299. outlineJson.Append("]");
  300. bool percent = Height.Type == UnitType.Percentage;
  301. string pageHeight = ((_pageHeight + Padding.Vertical) /* * (Height.Value / 100)*/ * Prop.Zoom)
  302. .ToString().Replace(',','.') + "px";
  303. string navRequest = string.Format("frRequestServer('{0}?previewobject={1}&goto=' + val + '{2}')",
  304. Prop.HandlerURL, // 0
  305. Prop.ControlID, // 1
  306. WebUtils.GetSalt()); // 2
  307. sb.Append("<div class=\"froutline\">")
  308. .Append(percent ? "<div class=\"froutline2\" style=\"max-height:" + pageHeight + "\">" : "")
  309. .Append("<style>")
  310. .Append(GetResource("jstree.style.min.css")
  311. .Replace("32px.png", GetResourceUrl("jstree.32px.png")) // replace pictures links
  312. .Replace("40px.png", GetResourceUrl("jstree.40px.png"))
  313. .Replace("throbber.gif", GetResourceUrl("jstree.throbber.gif")))
  314. .Append("</style>")
  315. .Append("<style>.gutter.gutter-horizontal { height:" + (percent ? pageHeight : ("calc(100% - " + Prop.ToolbarHeight.ToString() + "px)")) + "; }</style>")
  316. .Append("<script>")
  317. .Append("(function(){").Append(GetResource("jstree.jstree.min.js")).Append("})();")
  318. .Append("(function(){").Append(GetResource("split.split.min.js")).Append("}).call(frOutline);")
  319. .Append("frOutline(") // call frOutline function
  320. .Append(outlineJson) // 1st param of frOutline function
  321. .Append(",\"").Append(WebUtils.JavaScriptStringEncode(ReportGuid)).Append("\",") // 2nd param of frOutline function
  322. .Append("function(val){" + navRequest + ";});") // 3rd param of frOutline function
  323. .Append("</script>")
  324. .Append("<div class=\"froutlinecontainer\"></div>")
  325. .Append(percent ? "</div>" : "") // froutline2
  326. .Append("</div>"); // froutline
  327. }
  328. private void BuildOutline(StringBuilder sb, XmlItem xml, bool top)
  329. {
  330. for (int i = 0; i < xml.Count; i++)
  331. {
  332. sb.Append("{");
  333. XmlItem node = xml[i];
  334. string text = node.GetProp("Text");
  335. int page = 0;
  336. float offset = 0f;
  337. string s = node.GetProp("Page");
  338. if (s != "")
  339. {
  340. page = int.Parse(s);
  341. s = node.GetProp("Offset");
  342. if (s != "")
  343. offset = (float)Converter.FromString(typeof(float), s)/* * PDF_DIVIDER*/;
  344. }
  345. // id for saving tree state
  346. sb.Append("\"id\":\"").Append(WebUtils.JavaScriptStringEncode(ReportGuid + "_" + text + "_" + page + "_" + offset + "_" + sb.Length)).Append("\",");
  347. sb.Append("\"text\":\"").Append(WebUtils.JavaScriptStringEncode(text)).Append("\",");
  348. sb.Append("\"data\":{")
  349. .Append("\"page\":").Append(page)
  350. .Append(",\"offset\":").Append(offset.ToString().Replace(',', '.'))
  351. .Append("}");
  352. // open if there is only one node on top
  353. if (top && xml.Count == 1)
  354. sb.Append(",\"state\":{\"opened\":true}");
  355. if (node.Count > 0)
  356. {
  357. sb.Append(",\"children\": [");
  358. BuildOutline(sb, node, false);
  359. sb.Append("]");
  360. }
  361. sb.Append("}");
  362. // don't add comma if it is the last node
  363. if (i < xml.Count - 1)
  364. sb.Append(",");
  365. }
  366. }
  367. private string GetResource(string resName)
  368. {
  369. string result;
  370. using (Stream stream = typeof(WebReport).Assembly.GetManifestResourceStream("FastReport.Web.Resources." + resName))
  371. using (TextReader reader = new StreamReader(stream))
  372. result = reader.ReadToEnd();
  373. return result;
  374. }
  375. private string GetResourceUrl(string resName)
  376. {
  377. return Page.ClientScript.GetWebResourceUrl(this.GetType(), "FastReport.Web.Resources." + resName);
  378. }
  379. }
  380. }