最近项目里需要把以前的客户问题数据导入到新的系统中来,从开始到完成整整花了一天半的时间,现把大概的一些开发过程记录如下:
一.分析
图A
图B
要从A中的内容转成B,先分析图A
1.A中内容是经过base64编码过的;
2.A中可能有0张或1张以上图片;
3.转化后看出内容是rtf格式
,所以,核心是rtf格式的转化是实现的难点。
二.实现
1.从数据库里读出数据(略)
2.把 解码 base64的内容成字符串
1 string strPress= Decompress(Convert.FromBase64String(QuestionContent)) 2 3 4 5 6 /// <summary> 7 /// 解压缩字符串 8 /// </summary> 9 /// <param name="buf">压缩后的的数据</param> 10 /// <returns>解压后的数据</returns> 11 public static string Decompress(byte[] buf) 12 { 13 if (buf.Length < 1) 14 return ""; 15 16 long totalLength = 0; 17 int size = 0; 18 MemoryStream ms = new MemoryStream(), msD = new MemoryStream(); 19 ms.Write(buf, 0, buf.Length); 20 ms.Seek(0, SeekOrigin.Begin); 21 GZipStream zip; 22 zip = new GZipStream(ms, CompressionMode.Decompress); 23 byte[] db; 24 bool readed = false; 25 while (true) 26 { 27 size = zip.ReadByte(); 28 if (size != -1) 29 { 30 if (!readed) readed = true; 31 totalLength++; 32 msD.WriteByte((byte)size); 33 } 34 else 35 { 36 if (readed) break; 37 } 38 } 39 zip.Close(); 40 db = msD.ToArray(); 41 msD.Close(); 42 return Encoding.UTF8.GetString(db); 43 }
转后,就是主要对rtf格式的转化,先正则把图片代码保存起来
1 /// <summary> 2 /// 找出图片并格式化 3 /// </summary> 4 /// <param name="RtfText"></param> 5 void SeparateImage(int QuestionId, string RtfText) 6 { 7 string TemRtfText = RtfText; 8 int Sg = 1; 9 string pattern = @"{\\pict(.|\n)*?}"; 10 while (true) 11 { 12 int _Index = TemRtfText.IndexOf("pichgoal"); 13 if (_Index == -1) break; 14 RtfImage img = new RtfImage(); 15 Match mat = Regex.Match(TemRtfText, @"picwgoal[\d]+"); 16 img.Width = int.Parse(mat.Value.Replace("picwgoal", "")) / 15; 17 mat = Regex.Match(TemRtfText, @"pichgoal[\d]+"); 18 img.Height = int.Parse(mat.Value.Replace("pichgoal", "")) / 15; 19 TemRtfText = TemRtfText.Remove(0, _Index + 8); 20 _Index = TemRtfText.IndexOf("\r\n"); 21 TemRtfText = TemRtfText.Remove(0, _Index); 22 _Index = TemRtfText.IndexOf("}"); 23 img.FexCode = TemRtfText.Substring(0, _Index).Replace("\r\n", ""); 24 img.File = DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpeg"; 25 string RepTag = string.Format("[$$img{0}$$]", Sg); 26 img.RepTag = RepTag; 27 if (Regex.IsMatch(RtfText, pattern)) 28 { 29 RtfText = RtfText.Replace(Regex.Match(RtfText, pattern).Groups[0].Value, RepTag); 30 } 31 TemRtfText = TemRtfText.Remove(0, _Index); 32 ListImage.Add(img); 33 Sg++; 34 } 35 ImageSave(QuestionId, RtfText); 36 }
保存图片
1 /// <summary> 2 /// 保存图片 3 /// </summary> 4 void ImageSave(int QuestionId, string RtfText) 5 { 6 foreach (var img in ListImage) 7 { 8 Byte[] buffer; 9 buffer = null; 10 int _Count = img.FexCode.Length / 2; 11 buffer = new Byte[img.FexCode.Length / 2]; 12 13 for (int z = 0; z != _Count; z++) 14 { 15 string _TempText = img.FexCode[z * 2].ToString() + img.FexCode[(z * 2) + 1].ToString(); 16 buffer[z] = Convert.ToByte(_TempText, 16); 17 } 18 19 Action ac = () => 20 { 21 MemoryStream ms = new MemoryStream(buffer); 22 Image _a = Image.FromStream(ms); 23 Bitmap bm = new Bitmap(_a, new Size(img.Width, img.Height)); 24 string file = img.File; 25 lbpic.Text = (Convert.ToInt32(lbpic.Text) + 1).ToString(); 26 txtPic.Text += file + "\n"; 27 bm.Save(string.Format("{0}{1}", Config.SavePath, file), System.Drawing.Imaging.ImageFormat.Bmp); 28 ms.Close(); 29 _a.Dispose(); 30 }; 31 ac.Invoke(); 32 Thread.Sleep(100); 33 } 34 ParseToHtml(QuestionId, RtfText); 35 }
解析RTf参考了下国外的一篇文章,网址现记不清楚了,
大概代码如下

1 public static class HtmlFromXamlConverter 2 { 3 // --------------------------------------------------------------------- 4 // 5 // Internal Methods 6 // 7 // --------------------------------------------------------------------- 8 9 #region Internal Methods 10 11 /// <summary> 12 /// Main entry point for Xaml-to-Html converter. 13 /// Converts a xaml string into html string. 14 /// </summary> 15 /// <param name="xamlString"> 16 /// Xaml strinng to convert. 17 /// </param> 18 /// <returns> 19 /// Html string produced from a source xaml. 20 /// </returns> 21 public static string ConvertXamlToHtml(string xamlString, bool asFullDocument) 22 { 23 XmlTextReader xamlReader; 24 StringBuilder htmlStringBuilder; 25 XmlTextWriter htmlWriter; 26 27 xamlReader = new XmlTextReader(new StringReader(xamlString)); 28 29 htmlStringBuilder = new StringBuilder(100); 30 htmlWriter = new XmlTextWriter(new StringWriter(htmlStringBuilder)); 31 32 if (!WriteFlowDocument(xamlReader, htmlWriter, asFullDocument)) 33 { 34 return ""; 35 } 36 37 string htmlString = htmlStringBuilder.ToString(); 38 39 return htmlString; 40 } 41 42 #endregion Internal Methods 43 44 // --------------------------------------------------------------------- 45 // 46 // Private Methods 47 // 48 // --------------------------------------------------------------------- 49 50 #region Private Methods 51 /// <summary> 52 /// Processes a root level element of XAML (normally it's FlowDocument element). 53 /// </summary> 54 /// <param name="xamlReader"> 55 /// XmlTextReader for a source xaml. 56 /// </param> 57 /// <param name="htmlWriter"> 58 /// XmlTextWriter producing resulting html 59 /// </param> 60 private static bool WriteFlowDocument(XmlTextReader xamlReader, XmlTextWriter htmlWriter, bool asFullDocument) 61 { 62 if (!ReadNextToken(xamlReader)) 63 { 64 // Xaml content is empty - nothing to convert 65 return false; 66 } 67 68 if (xamlReader.NodeType != XmlNodeType.Element || xamlReader.Name != "FlowDocument") 69 { 70 // Root FlowDocument elemet is missing 71 return false; 72 } 73 74 // Create a buffer StringBuilder for collecting css properties for inline STYLE attributes 75 // on every element level (it will be re-initialized on every level). 76 StringBuilder inlineStyle = new StringBuilder(); 77 78 if (asFullDocument) 79 { 80 htmlWriter.WriteStartElement("HTML"); 81 htmlWriter.WriteStartElement("BODY"); 82 } 83 WriteFormattingProperties(xamlReader, htmlWriter, inlineStyle); 84 85 WriteElementContent(xamlReader, htmlWriter, inlineStyle); 86 87 if (asFullDocument) 88 { 89 htmlWriter.WriteEndElement(); 90 htmlWriter.WriteEndElement(); 91 } 92 return true; 93 } 94 95 /// <summary> 96 /// Reads attributes of the current xaml element and converts 97 /// them into appropriate html attributes or css styles. 98 /// </summary> 99 /// <param name="xamlReader"> 100 /// XmlTextReader which is expected to be at XmlNodeType.Element 101 /// (opening element tag) position. 102 /// The reader will remain at the same level after function complete. 103 /// </param> 104 /// <param name="htmlWriter"> 105 /// XmlTextWriter for output html, which is expected to be in 106 /// after WriteStartElement state. 107 /// </param> 108 /// <param name="inlineStyle"> 109 /// String builder for collecting css properties for inline STYLE attribute. 110 /// </param> 111 private static void WriteFormattingProperties(XmlTextReader xamlReader, XmlTextWriter htmlWriter, StringBuilder inlineStyle) 112 { 113 Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); 114 115 // Clear string builder for the inline style 116 inlineStyle.Remove(0, inlineStyle.Length); 117 118 if (!xamlReader.HasAttributes) 119 { 120 return; 121 } 122 123 bool borderSet = false; 124 125 while (xamlReader.MoveToNextAttribute()) 126 { 127 string css = null; 128 129 switch (xamlReader.Name) 130 { 131 // Character fomatting properties 132 // ------------------------------ 133 case "Background": 134 css = "background-color:" + ParseXamlColor(xamlReader.Value) + ";"; 135 break; 136 case "FontFamily": 137 css = "font-family:" + xamlReader.Value + ";"; 138 break; 139 case "FontStyle": 140 css = "font-style:" + xamlReader.Value.ToLower() + ";"; 141 break; 142 case "FontWeight": 143 css = "font-weight:" + xamlReader.Value.ToLower() + ";"; 144 break; 145 case "FontStretch": 146 break; 147 case "FontSize": 148 css = "font-size:" + xamlReader.Value + ";"; 149 break; 150 case "Foreground": 151 css = "color:" + ParseXamlColor(xamlReader.Value) + ";"; 152 break; 153 case "TextDecorations": 154 if (xamlReader.Value.ToLower() == "strikethrough") 155 css = "text-decoration:line-through;"; 156 else 157 css = "text-decoration:underline;"; 158 break; 159 case "TextEffects": 160 break; 161 case "Emphasis": 162 break; 163 case "StandardLigatures": 164 break; 165 case "Variants": 166 break; 167 case "Capitals": 168 break; 169 case "Fraction": 170 break; 171 172 // Paragraph formatting properties 173 // ------------------------------- 174 case "Padding": 175 css = "padding:" + ParseXamlThickness(xamlReader.Value) + ";"; 176 break; 177 case "Margin": 178 css = "margin:" + ParseXamlThickness(xamlReader.Value) + ";"; 179 break; 180 case "BorderThickness": 181 css = "border-width:" + ParseXamlThickness(xamlReader.Value) + ";"; 182 borderSet = true; 183 break; 184 case "BorderBrush": 185 css = "border-color:" + ParseXamlColor(xamlReader.Value) + ";"; 186 borderSet = true; 187 break; 188 case "LineHeight": 189 break; 190 case "TextIndent": 191 css = "text-indent:" + xamlReader.Value + ";"; 192 break; 193 case "TextAlignment": 194 css = "text-align:" + xamlReader.Value + ";"; 195 break; 196 case "IsKeptTogether": 197 break; 198 case "IsKeptWithNext": 199 break; 200 case "ColumnBreakBefore": 201 break; 202 case "PageBreakBefore": 203 break; 204 case "FlowDirection": 205 break; 206 207 // Table attributes 208 // ---------------- 209 case "Width": 210 css = "width:" + xamlReader.Value + ";"; 211 break; 212 case "ColumnSpan": 213 htmlWriter.WriteAttributeString("COLSPAN", xamlReader.Value); 214 break; 215 case "RowSpan": 216 htmlWriter.WriteAttributeString("ROWSPAN", xamlReader.Value); 217 break; 218 219 // Hyperlink Attributes 220 case "NavigateUri": 221 htmlWriter.WriteAttributeString("HREF", xamlReader.Value); 222 break; 223 224 case "TargetName": 225 htmlWriter.WriteAttributeString("TARGET", xamlReader.Value); 226 break; 227 } 228 229 if (css != null) 230 { 231 inlineStyle.Append(css); 232 } 233 } 234 235 if (borderSet) 236 { 237 inlineStyle.Append("border-style:solid;mso-element:para-border-div;"); 238 } 239 240 // Return the xamlReader back to element level 241 xamlReader.MoveToElement(); 242 Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); 243 } 244 245 private static string ParseXamlColor(string color) 246 { 247 if (color.StartsWith("#")) 248 { 249 // Remove transparancy value 250 color = "#" + color.Substring(3); 251 } 252 return color; 253 } 254 255 private static string ParseXamlThickness(string thickness) 256 { 257 string[] values = thickness.Split(','); 258 259 for (int i = 0; i < values.Length; i++) 260 { 261 double value; 262 if (double.TryParse(values[i], out value)) 263 { 264 values[i] = Math.Ceiling(value).ToString(); 265 } 266 else 267 { 268 values[i] = "1"; 269 } 270 } 271 272 string cssThickness; 273 switch (values.Length) 274 { 275 case 1: 276 cssThickness = thickness; 277 break; 278 case 2: 279 cssThickness = values[1] + " " + values[0]; 280 break; 281 case 4: 282 cssThickness = values[1] + " " + values[2] + " " + values[3] + " " + values[0]; 283 break; 284 default: 285 cssThickness = values[0]; 286 break; 287 } 288 289 return cssThickness; 290 } 291 292 /// <summary> 293 /// Reads a content of current xaml element, converts it 294 /// </summary> 295 /// <param name="xamlReader"> 296 /// XmlTextReader which is expected to be at XmlNodeType.Element 297 /// (opening element tag) position. 298 /// </param> 299 /// <param name="htmlWriter"> 300 /// May be null, in which case we are skipping the xaml element; 301 /// witout producing any output to html. 302 /// </param> 303 /// <param name="inlineStyle"> 304 /// StringBuilder used for collecting css properties for inline STYLE attribute. 305 /// </param> 306 private static void WriteElementContent(XmlTextReader xamlReader, XmlTextWriter htmlWriter, StringBuilder inlineStyle) 307 { 308 Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); 309 310 bool elementContentStarted = false; 311 312 if (xamlReader.IsEmptyElement) 313 { 314 if (htmlWriter != null && !elementContentStarted && inlineStyle.Length > 0) 315 { 316 // Output STYLE attribute and clear inlineStyle buffer. 317 htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString()); 318 inlineStyle.Remove(0, inlineStyle.Length); 319 } 320 elementContentStarted = true; 321 } 322 else 323 { 324 while (ReadNextToken(xamlReader) && xamlReader.NodeType != XmlNodeType.EndElement) 325 { 326 switch (xamlReader.NodeType) 327 { 328 case XmlNodeType.Element: 329 if (xamlReader.Name.Contains(".")) 330 { 331 AddComplexProperty(xamlReader, inlineStyle); 332 } 333 else 334 { 335 if (htmlWriter != null && !elementContentStarted && inlineStyle.Length > 0) 336 { 337 // Output STYLE attribute and clear inlineStyle buffer. 338 htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString()); 339 inlineStyle.Remove(0, inlineStyle.Length); 340 } 341 elementContentStarted = true; 342 WriteElement(xamlReader, htmlWriter, inlineStyle); 343 } 344 Debug.Assert(xamlReader.NodeType == XmlNodeType.EndElement || xamlReader.NodeType == XmlNodeType.Element && xamlReader.IsEmptyElement); 345 break; 346 case XmlNodeType.Comment: 347 if (htmlWriter != null) 348 { 349 if (!elementContentStarted && inlineStyle.Length > 0) 350 { 351 htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString()); 352 } 353 htmlWriter.WriteComment(xamlReader.Value); 354 } 355 elementContentStarted = true; 356 break; 357 case XmlNodeType.CDATA: 358 case XmlNodeType.Text: 359 case XmlNodeType.SignificantWhitespace: 360 if (htmlWriter != null) 361 { 362 if (!elementContentStarted && inlineStyle.Length > 0) 363 { 364 htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString()); 365 } 366 htmlWriter.WriteString(xamlReader.Value); 367 } 368 elementContentStarted = true; 369 break; 370 } 371 } 372 373 Debug.Assert(xamlReader.NodeType == XmlNodeType.EndElement); 374 } 375 } 376 377 /// <summary> 378 /// Conberts an element notation of complex property into 379 /// </summary> 380 /// <param name="xamlReader"> 381 /// On entry this XmlTextReader must be on Element start tag; 382 /// on exit - on EndElement tag. 383 /// </param> 384 /// <param name="inlineStyle"> 385 /// StringBuilder containing a value for STYLE attribute. 386 /// </param> 387 private static void AddComplexProperty(XmlTextReader xamlReader, StringBuilder inlineStyle) 388 { 389 Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); 390 391 if (inlineStyle != null && xamlReader.Name.EndsWith(".TextDecorations")) 392 { 393 inlineStyle.Append("text-decoration:underline;"); 394 } 395 396 // Skip the element representing the complex property 397 WriteElementContent(xamlReader, /*htmlWriter:*/null, /*inlineStyle:*/null); 398 } 399 400 /// <summary> 401 /// Converts a xaml element into an appropriate html element. 402 /// </summary> 403 /// <param name="xamlReader"> 404 /// On entry this XmlTextReader must be on Element start tag; 405 /// on exit - on EndElement tag. 406 /// </param> 407 /// <param name="htmlWriter"> 408 /// May be null, in which case we are skipping xaml content 409 /// without producing any html output 410 /// </param> 411 /// <param name="inlineStyle"> 412 /// StringBuilder used for collecting css properties for inline STYLE attributes on every level. 413 /// </param> 414 private static void WriteElement(XmlTextReader xamlReader, XmlTextWriter htmlWriter, StringBuilder inlineStyle) 415 { 416 Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); 417 418 if (htmlWriter == null) 419 { 420 // Skipping mode; recurse into the xaml element without any output 421 WriteElementContent(xamlReader, /*htmlWriter:*/null, null); 422 } 423 else 424 { 425 string htmlElementName = null; 426 427 switch (xamlReader.Name) 428 { 429 case "Run": 430 case "Span": 431 htmlElementName = "SPAN"; 432 break; 433 case "InlineUIContainer": 434 htmlElementName = "SPAN"; 435 break; 436 case "Bold": 437 htmlElementName = "B"; 438 break; 439 case "Italic": 440 htmlElementName = "I"; 441 break; 442 case "Paragraph": 443 htmlElementName = "P"; 444 break; 445 case "BlockUIContainer": 446 htmlElementName = "DIV"; 447 break; 448 case "Section": 449 htmlElementName = "DIV"; 450 break; 451 case "Table": 452 htmlElementName = "TABLE"; 453 break; 454 case "TableColumn": 455 htmlElementName = "COL"; 456 break; 457 case "TableRowGroup": 458 htmlElementName = "TBODY"; 459 break; 460 case "TableRow": 461 htmlElementName = "TR"; 462 break; 463 case "TableCell": 464 htmlElementName = "TD"; 465 break; 466 case "List": 467 string marker = xamlReader.GetAttribute("MarkerStyle"); 468 if (marker == null || marker == "None" || marker == "Disc" || marker == "Circle" || marker == "Square" || marker == "Box") 469 { 470 htmlElementName = "UL"; 471 } 472 else 473 { 474 htmlElementName = "OL"; 475 } 476 break; 477 case "ListItem": 478 htmlElementName = "LI"; 479 break; 480 case "Hyperlink": 481 htmlElementName = "A"; 482 break; 483 default: 484 htmlElementName = null; // Ignore the element 485 break; 486 } 487 488 if (htmlWriter != null && htmlElementName != null) 489 { 490 htmlWriter.WriteStartElement(htmlElementName); 491 492 WriteFormattingProperties(xamlReader, htmlWriter, inlineStyle); 493 494 WriteElementContent(xamlReader, htmlWriter, inlineStyle); 495 496 htmlWriter.WriteEndElement(); 497 } 498 else 499 { 500 // Skip this unrecognized xaml element 501 WriteElementContent(xamlReader, /*htmlWriter:*/null, null); 502 } 503 } 504 } 505 506 // Reader advance helpers 507 // ---------------------- 508 509 /// <summary> 510 /// Reads several items from xamlReader skipping all non-significant stuff. 511 /// </summary> 512 /// <param name="xamlReader"> 513 /// XmlTextReader from tokens are being read. 514 /// </param> 515 /// <returns> 516 /// True if new token is available; false if end of stream reached. 517 /// </returns> 518 private static bool ReadNextToken(XmlReader xamlReader) 519 { 520 while (xamlReader.Read()) 521 { 522 Debug.Assert(xamlReader.ReadState == ReadState.Interactive, "Reader is expected to be in Interactive state (" + xamlReader.ReadState + ")"); 523 switch (xamlReader.NodeType) 524 { 525 case XmlNodeType.Element: 526 case XmlNodeType.EndElement: 527 case XmlNodeType.None: 528 case XmlNodeType.CDATA: 529 case XmlNodeType.Text: 530 case XmlNodeType.SignificantWhitespace: 531 return true; 532 533 case XmlNodeType.Whitespace: 534 if (xamlReader.XmlSpace == XmlSpace.Preserve) 535 { 536 return true; 537 } 538 // ignore insignificant whitespace 539 break; 540 541 case XmlNodeType.EndEntity: 542 case XmlNodeType.EntityReference: 543 // Implement entity reading 544 //xamlReader.ResolveEntity(); 545 //xamlReader.Read(); 546 //ReadChildNodes( parent, parentBaseUri, xamlReader, positionInfo); 547 break; // for now we ignore entities as insignificant stuff 548 549 case XmlNodeType.Comment: 550 return true; 551 case XmlNodeType.ProcessingInstruction: 552 case XmlNodeType.DocumentType: 553 case XmlNodeType.XmlDeclaration: 554 default: 555 // Ignorable stuff 556 break; 557 } 558 } 559 return false; 560 } 561 562 #endregion Private Methods 563 564 // --------------------------------------------------------------------- 565 // 566 // Private Fields 567 // 568 // --------------------------------------------------------------------- 569 570 #region Private Fields 571 572 #endregion Private Fields 573 }

1 class RtfToHtmlConverter 2 { 3 private const string FlowDocumentFormat = "<FlowDocument>{0}</FlowDocument>"; 4 5 public static string ConvertRtfToHtml(string rtfText) 6 { 7 var xamlText = string.Format(FlowDocumentFormat, ConvertRtfToXaml(rtfText)); 8 9 return HtmlFromXamlConverter.ConvertXamlToHtml(xamlText, false); 10 } 11 private static string ConvertRtfToXaml(string rtfText) 12 { 13 RichTextBox richTextBox = new RichTextBox(); 14 if (string.IsNullOrEmpty(rtfText)) return ""; 15 16 var textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); 17 18 //Create a MemoryStream of the Rtf content 19 20 using (var rtfMemoryStream = new MemoryStream()) 21 { 22 using (var rtfStreamWriter = new StreamWriter(rtfMemoryStream)) 23 { 24 rtfStreamWriter.Write(rtfText); 25 rtfStreamWriter.Flush(); 26 rtfMemoryStream.Seek(0, SeekOrigin.Begin); 27 28 //Load the MemoryStream into TextRange ranging from start to end of RichTextBox. 29 textRange.Load(rtfMemoryStream, DataFormats.Rtf); 30 } 31 } 32 33 using (var rtfMemoryStream = new MemoryStream()) 34 { 35 36 textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); 37 textRange.Save(rtfMemoryStream, DataFormats.Xaml); 38 rtfMemoryStream.Seek(0, SeekOrigin.Begin); 39 using (var rtfStreamReader = new StreamReader(rtfMemoryStream)) 40 { 41 return rtfStreamReader.ReadToEnd(); 42 } 43 } 44 45 } 46 }
这样的之后,就可以直接转化了

1 /// <summary> 2 /// 转化成html且保存到数据库 3 /// </summary> 4 /// <param name="QuestionId"></param> 5 /// <param name="strCompress"></param> 6 void ParseToHtml(int QuestionId, string strCompress) 7 { 8 string StrRely = RtfToHtmlConverter.ConvertRtfToHtml(strCompress); 9 10 foreach (var img in ListImage) 11 { 12 StrRely = StrRely.Replace(img.RepTag, "<img src='" + string.Format("{0}{1}", Config.SiteUrl, img.File) + "' width='" + img.Width + "' height='" + img.Height + "'/>"); 13 14 } 15 DbExecute db = new DbExecute("CRM"); 16 lbdata.Text = (Convert.ToInt32(lbdata.Text) + 1).ToString(); 17 db.Parameter.Add("QuestionId", QuestionId); 18 db.Parameter.Add("QuestionContent", StrRely.ToLower()); 19 db.NonQuery("QuestionParseUpdate"); 20 DoEnd(); 21 }