В прошлом посте мы сохраняли в базу контент в HTML формате, но проблема была в том, что программа c TRichView копировала изображение в некую директорию и прописывала пути относительно неё. Оно и записывалось и читалось корректно, но в пределах одного компьютера. Если же, скажем, нам нужно прочитать контент, в котором картинка на некотором удаленном сервере, а пусть даже и на локальном, то такой вариант бы не прокатил. Короче, хотелось сделать по нормальному, по человечески, как это работает в традиционном WEB.
То есть, если картинка, то в базе она должна записываться как
1 |
<img class="aligncenter wp-image-5219" src="http://digital-flame.ru/wp-content/uploads/2016/08/1-1024x331.jpg" alt="1" width="700" height="227" /> |
а не просто
1 |
pic1.jpg |
Как же этого добиться? Пару дней покопавшись с документацией TRichView я пришел к такому вот решению.
Прежде всего, нам нужно обработать событие RvHtmlImporterImageRequired2 у компонента RvHtmlImporter
вот таким вот образом…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
procedure TVisualFrame.RvHtmlImporterImageRequired2(Sender: TObject; const src: string; Width, Height: Integer; var Img: TGraphic); var FileName: string; Index: Integer; Stream: TMemoryStream; TempFileName: string; FileStream: TFileStream; pic: TPicture; Img2: TGraphic; bmp:TBitmap; image:Timage; begin try Img:=nil; // Определяем путь картинки if Pos(':', src)>0 then FileName := src // absolute path else FileName := RvHtmlImporter.BasePath+src; // relative path //Если такое изображение уже есть среди загруженных - берем его в Img Index:= DownLoadedImages.IndexOf(FileName); if Index<>-1 then begin Img := RV_CreateGraphics(TGraphicClass(TGraphic(DownloadedImages.Objects[Index]).ClassType)); Img.Assign(TGraphic(DownloadedImages.Objects[Index])); exit; end; //Продолжаем. Если его там нет - загружаем из сети if (Pos('http://', LowerCase(FileName))<>0) or (Pos('https://', LowerCase(FileName))<>0) then begin Stream := TMemoryStream.Create; Stream.Position:=0; try // 1. Downloading IdHTTP.Get(FileName,Stream); Stream.Position:=0; // 2. creating temporal file TempFileName := GetTempFileName(ExtractFileExt(src)); FileStream := TFileStream.Create(TempFileName, fmCreate); try FileStream.CopyFrom(Stream,0); finally FreeAndNil(FileStream); end; // 3.reading and deleting temporal file pic := TPicture.Create; try pic. LoadFromFile(TempFileName); Img := RV_CreateGraphics(TGraphicClass(pic.Graphic.ClassType)); Img.Assign(pic.Graphic); finally FreeAndNil(pic); DeleteFile(TempFileName); end; // finally FreeAndNil(Stream); end; end else { READING IF LOCAL FILE } begin pic := TPicture.Create; try pic.LoadFromFile(FileName); Img := RV_CreateGraphics(TGraphicClass(pic.Graphic.ClassType)); Img.Assign(pic.Graphic); finally FreeAndNil(pic); end; end; // ADDING TO DOWNLOADED if not NIL if Img<>nil then begin Img2 := RV_CreateGraphics(TGraphicClass(Img.ClassType)); Img2.Assign(Img); DownloadedImages.AddObject(FileName, Img2) end; except Img.Free; Img := nil; end; //Если ничего не загрузислось ниоткуда... if Img=nil then begin { FAILED. CREATING DEFAULT IMAGE } if Width=0 then Width := 23; if Height=0 then Height := 23; Img := TBitmap.Create; Img.Width := Width; Img.Height := Height; TBitmap(Img).Canvas.Pen.Color := clRed; TBitmap(Img).Canvas.Font.Color := clRed; TBitmap(Img).Canvas.Rectangle(0,0,Width,Height); TBitmap(Img).Canvas.TextOut(2, 2, '?!'); Img2 := RV_CreateGraphics(TGraphicClass(Img.ClassType)); Img2.Assign(Img); DownloadedImages.AddObject(FileName, Img2) end; end; |
Далее, нам нужно обработать событие OnSaveImage2 у компонента RichViewEdit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
procedure TVisualFrame.RichViewEditSaveImage2(Sender: TCustomRichView; Graphic: TGraphic; SaveFormat: TRVSaveFormat; const Path, ImagePrefix: string; var ImageSaveNo: Integer; var Location: string; var DoDefault: Boolean); var URL:string; begin DoDefault:=False; RichViewEdit.TopLevelEditor.BeginUndoGroup(rvutInsert); RichViewEdit.TopLevelEditor.SetUndoGroupMode(True); if RichViewEdit.InsertPicture('', Graphic, rvvaBaseline) then RichViewEdit.SetCurrentItemExtraStrProperty(rvespImageFileName, URL, True); RichViewEdit.TopLevelEditor.SetUndoGroupMode(False); end; |
Теперь, если поработать с программой, то код в базе будет выглядеть например так…
1 2 3 4 5 6 7 8 9 |
<body> <p class=rvps1><img width=700 height=151 alt="5" src="http://digital-flame.ru/wp-content/uploads/2016/08/5-1024x220.jpg"></p> <p><br></p> <p class=rvps1><a href="http://digital-flame.ru/wp-content/uploads/2016/08/2.jpg"><img width=300 height=390 alt="2" src="http://digital-flame.ru/wp-content/uploads/2016/08/2.jpg"></a></p> <p class=rvps1><br></p> <p>Разрабатываю небольшой компонент - текстовый редактор DBTextEditor, для своей программы . В базе данные будут храниться в HTML формате в обычном текстовом поле. У меня MySQL, я использую TEXT поле. Изображения будут храниться рядом с EXE - в отдельной папке Pics, а в базе будут только ссылки на изображение - что избавит от раздутия таблиц при использовании BLOB полей. Компонент разрабатываю с помощью фрэйма. То есть, доступ ко всем полям и методам будет примерно таким <span class=rvts12>DBTextEditor.VisualFrame.SomeMethod</span> Выглядит фрэйм примерно таким образом </p> <p><br></p> <p class=rvps1><a href="http://digital-flame.ru/wp-content/uploads/2016/08/1.jpg"><img width=700 height=227 alt="1" src="pic1.jpg"></a></p> </body> |
Как видно – картинки отображаются адекватно теперь.