- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在处理项目时,我想将下载的图像保存在 blob 字段中。我使用 idHTTP 成功,但 UI 卡住。
我创建了一个程序,使用 ImageLoader 方法 (Image Loader page) 从 URL 下载图像。图片一切正常,但我无法将它们保存在数据库的特定字段中。
我该怎么做?
这是我的代码:
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;
如果我只想显示图像,代码可以完美运行。我如何使用流来保存它们?
最佳答案
问题
问题是 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
其他选项
向线程添加一个事件,您可以在每次图像完成加载时挂接该事件。
在事件处理程序中,您可以显示图像并将其放入数据库。
事实上,异步加载器可能已经有一个选项,但我对代码库的了解还不足以回答这个问题。
关于android - 如何将线程结果保存在数据库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23250355/
我是一名优秀的程序员,十分优秀!