2

I use the Delphi LoadFromFile function to insert Table1BLOBFIELD.LoadFromFile ('C:\xxx.avi') and the SaveToFile command to retrieve. This inserting/retrieving is rather timeconsuming (several minutes). It would be nice if I could show a kind of progressbar (instead of only an hourglass-shaped cursor). When using SaveToFile I can perhaps use a timer and check the filesize (although this doesn't seem to work without threads). But this is no solution for LoadFromFile. Does anyone have a particular solution, a hint,...? Thanks in advance

riad
  • 361
  • 1
  • 9
  • 19
  • 1
    You could modify [this answer](http://stackoverflow.com/a/6082206/757830) which was written for `TResourceStream.SaveToFile`. – NGLN Feb 05 '13 at 11:14
  • Same kind of suggestion here: http://www.delphigroups.info/2/c3/138402.html – Jan Doggen Feb 05 '13 at 11:17
  • thanks, I'll take a look to the two suggestions – riad Feb 05 '13 at 11:53
  • @NGLN the procedure SaveToFile you used belongs to an object that inherits from TResourceStream, but in my case I want to use SaveToFile procedure that belongs to TBloBField class – riad Feb 05 '13 at 13:37
  • Yes, I understood. Hence a comment and not an answer. Will look into it this afternoon though. – NGLN Feb 05 '13 at 13:54

2 Answers2

7

Here a simple example of how to subclass TFileStream and how to add an OnProgress event to it:

unit Unit1;

interface

uses
  SysUtils, Classes, Controls, Forms, XPMan, Db, ComCtrls, StdCtrls, AdoDB;

type
  TStreamProgressEvent = procedure(Sender: TObject;
    Percentage: Single) of object;

  TProgressFileStream = class(TFileStream)
  private
    FOnProgress: TStreamProgressEvent;
    FProcessed: Int64;
    FSize: Int64;
  public
    procedure InitProgressCounter(ASize: Int64);
    function Read(var Buffer; Count: Integer): Integer; override;
    function Write(const Buffer; Count: Integer): Integer; override;
    property OnProgress: TStreamProgressEvent read FOnProgress
      write FOnProgress;
  end;

  TForm1 = class(TForm)
    ADOQuery1: TADOQuery;
    ADOQuery1ID: TAutoIncField;
    ADOQuery1Blob: TBlobField;
    Button1: TButton;
    ProgressBar: TProgressBar;
    procedure Button1Click(Sender: TObject);
  private
    procedure StreamProgress(Sender: TObject; Percentage: Single);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TProgressFileStream }

procedure TProgressFileStream.InitProgressCounter(ASize: Int64);
begin
  FProcessed := 0;
  if ASize <= 0 then
    FSize := 1
  else
    FSize := ASize;
  if Assigned(FOnProgress) then
    FOnProgress(Self, 0);
end;

function TProgressFileStream.Read(var Buffer; Count: Integer): Integer;
begin
  Result := inherited Read(Buffer, Count);
  Inc(FProcessed, Result);
  if Assigned(FOnProgress) then
    FOnProgress(Self, FProcessed / FSize);
end;

function TProgressFileStream.Write(const Buffer; Count: Integer): Integer;
begin
  Result := inherited Write(Buffer, Count);
  Inc(FProcessed, Result);
  if Assigned(FOnProgress) then
    FOnProgress(Self, FProcessed / FSize);
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  Stream: TProgressFileStream;
begin
  ADOQuery1.Open;
  Stream := TProgressFileStream.Create('H:\Delphi\Blobtest.docx', fmOpenRead);
  try
    Stream.OnProgress := StreamProgress;
    Stream.InitProgressCounter(Stream.Size);
    ADOQuery1.Append;
    ADOQuery1Blob.LoadFromStream(Stream);
    ADOQuery1.Post;
  finally
    Stream.Free;
  end;
  Stream := TProgressFileStream.Create('H:\Delphi\Blobtest2.docx', fmCreate);
  try
    ADOQuery1.Last;
    Stream.OnProgress := StreamProgress;
    Stream.InitProgressCounter(ADOQuery1Blob.BlobSize);
    ADOQuery1Blob.SaveToStream(Stream);
  finally
    Stream.Free;
  end;
end;

procedure TForm1.StreamProgress(Sender: TObject; Percentage: Single);
begin
  ProgressBar.Position := Round(Percentage * ProgressBar.Max);
end;

end.

Although this OnProgress event is implemented on the file-side of the process, the actual progress that it represents is the overall process, including database communication.

NGLN
  • 43,011
  • 8
  • 105
  • 200
1

I think the delay is not for reading the file but for the record in the database. I believe that you can make an estimate according to the file size, and project progress using a "TTimer," but for this reading the file should be done in a thread so that the rest of the application (Main Thread) latches

Edgard Leal
  • 2,592
  • 26
  • 30
  • Thanks, it's the solution proposed here http://delphigroups.info/2/c3/138402.html and I'm checking it out – riad Feb 05 '13 at 13:13