处理项目,我想保存我在blob字段中下载的图像。我成功使用idHTTP但UI冻结。
我创建了一个使用ImageLoader方法(Image Loader page)从URL下载图像的过程。图像一切正常,但我无法将它们保存在DB中的特定字段中。
我该怎么做?
这是我的代码:
procedure TForm1.LoadImages;
var
i: integer;
IMLO: TImageLoader;
IM: TImage;
Stream: TMemoryStream;
imgAddress: string;
begin
Table1.First;
for i := 0 to Table1.RecordCount-1 do
begin
imgAddress := Table1.FieldByName('URL').AsString;
Stream := TMemoryStream.Create;
IM:= TImage.Create(self);
IM.Name := 'IM'+inttostr(i);
IM.Parent := HorzScrollBox1;
IM.Position.X := i * 320;
IM.Align:= TAlignLayout.alLeft;
IM.Width := 300;
IMLO.LoadImage(IM, imgAddress);
{ Table1.Edit;
TBlobField(Table1.FieldByName('image')).LoadFromStream(Stream);
Table1.Post;
Stream.Free; }
Table1.Next;
end;
end;
如果我只想显示图像,代码可以正常工作。如何使用流来保存它们?
答案 0 :(得分:1)
<强>问题强>
问题是TImageLoader.LoadImage
异步加载来自网络的数据
因此,当您重新加载数据时,数据尚未可用。
简单解决方案
为了阻止TImageLoader执行此操作,您可以为其添加一个额外的方法并调用该方法
另一个问题是您使用Stream
数据加载Blob,但是您从不加载任何内容。
幸运的是,你不需要这条小溪。
function TImageLoader.LoadImageNow(const AImage: TImage; const AImageURL: string): boolean;
const
success = true;
failure = false;
var
MS : TMemoryStream;
Image: TImage;
begin
Result:= success;
MS := TMemoryStream.Create;
Image:= TImage.Create;
try
IdHTTP1.get(AImageURL,MS);
Ms.Seek(0,soFromBeginning);
Image.LoadFromStream(MS);
AImage.Picture.Assign(Image);
except
Result:= failure;
end;
FreeAndNil(Image);
FreeAndNil(MS);
end;
现在加载程序只会在加载图像时返回。
这也解释了为什么在释放IM
时获得例外
您正在释放IM,但加载程序仍在后台使用它
这就是使用多线程应用程序的问题,您需要跟踪其他线程正在做什么。
循环的代码现在看起来像这样:
procedure TForm1.LoadImages;
var
i: integer;
IMLO: TImageLoader;
IM: TImage;
imgAddress: string;
FieldImage: TGraphicField;
FieldUrl: TField;
begin
FieldImage:= TGraphicField(Table1.FieldByName('image'));
FieldUrl:= Table1.FieldByName('URL');
Table1.First;
for i := 0 to Table1.RecordCount-1 do try
imgAddress := FieldUrl.AsString;
IM:= TImage.Create(self);
IM.Name := 'IM'+inttostr(i);
IM.Parent := HorzScrollBox1;
IM.Position.X := i * 320;
IM.Align:= TAlignLayout.alLeft;
IM.Width := 300;
if IMLO.LoadImageNow(IM, imgAddress) then begin
Table1.Edit;
FieldImage.Assign(IM.Picture);
Table1.Post;
end; {if}
finally
IM.Free;
Stream.Free;
Table1.Next;
end; {for .. try}
end;
因为FieldByName
很慢,所以最好将它从循环中拉出来(由于LoadImageNow
的速度慢,这可能无关紧要。)
请参阅:http://docwiki.embarcadero.com/Libraries/XE5/en/Data.DB.TBlobField.Assign
并且:http://docwiki.embarcadero.com/CodeExamples/XE3/en/HTTP_Get_%28Delphi%29
其他选项
在每次图像完成加载时可以挂钩的线程中添加一个事件
在事件处理程序中,您可以显示图像并将其放入数据库中
事实上,异步加载器可能已经有了一个选项,但我不知道该代码库足以回答这个问题。