We help IT Professionals succeed at work.

Sending EXE file using (Indy 10.5.8.0) IdTCPCLient/IdTCPServer

Ahmad_Egypt
Ahmad_Egypt asked
on
Hi,

   Anyone give me a real example of how to send an EXE file (size is up to 30 MB) from IdTCPClient to IdTCPServer.  and how to make a real progress bar indicating file sending/receiving progress. on both Applications (server & client).

 I am using Indy 10.5.8.0 with Delphi XE2.

My Client/Server Applications works only on my LAN, no WAN.

Many Thanks in Advance!
Comment
Watch Question

Mike McCrackenSenior Consultant
CERTIFIED EXPERT
Most Valuable Expert 2011
Top Expert 2013

Commented:
Why do you need to do this?

Will existing WIndows tools not allow you to copy a file from one machine to another?

mlmcc

Author

Commented:
it is a big system, we need employees to request update for an existing system from in-house IT, IT ppl update the application every now and then , and they just send a message using admin tool to all clients (employees 50+) telling them that there is an update available.

and then clients just request the update for the application. and admin tool will send it automatically.
Mike McCrackenSenior Consultant
CERTIFIED EXPERT
Most Valuable Expert 2011
Top Expert 2013

Commented:
There are tools available that will continuously or on a schedule update all PCs connected to a network with the latest versions.  I don't recall specific names but have you looked into using one of those?

mlmcc

Author

Commented:
why to use ready tools while I am a developer and can do it by my self ?

is it that hard using Indy ?

Commented:
Try it somehow like this...

Client Code:

procedure TForm1.Button1Click(Sender: TObject);
var
  fs: TFileStream;
  fn: string;
begin
  if (opendialog1.Execute) then fn:=opendialog1.FileName;

  if FileExists(fn) then begin
    fs := TFileStream.Create(fn, fmOpenRead);

    IdTCPClient1.Connect;
    IdTCPClient1.IOHandler.Write(fs);
    IdTCPClient1.Disconnect;
  end;
end;

Open in new window



Server code:

procedure TForm1.IdTCPServer1Execute(TheContext: TIdContext);
var
  fs: TFileStream;
begin
  fs := TFileStream.Create('c:\temp\tempfile.$$$', fmCreate);

  TheContext.Connection.IOHandler.ReadStream(fs);
end;

Open in new window

Commented:
Just to learn more about Delphi and Indy...

Exchanging Data over the Network using Delphi - Part 2

Commented:
This might help you implementing a progress bar...

How to implement a progress bar with TIdTCPClient?

Author

Commented:
Thommy I tried your code, it creates the file with 1 KB, and nothing after that.

and what about the progress ?

Commented:
Just wrote my code "quick & dirty" without testing it.

Should only show you the principle of transfering data with Indy!

Have a look at Indy's ImageServer Demo and also following former EE post especially for implementing progress bar:
Progress indicator using Indy's TCP client/server

Author

Commented:
Well, file transferred, same size... But...

as you know it is an EXE file, but it is corrupted, when i try to run it, it says that an application (client application) is using the file.. I close the client application and try to run the transferred file  , it is not a valid EXE file, even it is the same size.!!!

Commented:
Can you post you client and server code...

Author

Commented:
its worked after I updated the line on the Server Code:

   AContext.Connection.IOHandler.ReadStream(FileStream);

To This:

   AContext.Connection.IOHandler.ReadStream(FileStream, -1, True);


Anyway, below find the Code:


Client Code:

procedure TForm1.SendFileToClient(FName: string; IPAdd: string);
var
  FileStream : TFileStream;
begin
      FileStream := TFileStream.Create(FName, fmOpenRead);
      try
        UpdateClient.Host := IPAdd;
        UpdateClient.Port := 2007;
        UpdateClient.Connect;
        try
           try
              UpdateClient.IOHandler.Write(FileStream);
           finally
               UpdateClient.Disconnect;
           end;
        except
           on E: EIdException do
           begin
               //Network error occurred during communication
               ShowAMessage(2, 'Error Sending Update Files');
           end;
           on E: Exception do
           begin
               //Unknown error occurred during communication
               ShowAMessage(2, 'Error Sending Update Files');
           end;
        end;
      except
        on E: EIdException do
        begin
          //Network error occurred while trying to connect
          ShowAMessage(2, 'Error Connecting with Client');
        end;
        on E: Exception do
        begin
            //Unknown error occurred while trying to connect
           ShowAMessage(2, 'Error Connecting with Client');
        end;
      end;
end;

Open in new window



Server Code:
procedure TForm1.UpdateServerExecute(AContext: TIdContext);
var
  FileStream : TFileStream;
  FileLocation : String;
begin
   FileLocation := ExtractFileDir(ParamStr(0)) + '\Updates\' + 'AccInv.exe';
   ShowMessage(FileLocation);
   FileStream := TFileStream.Create(FileLocation, fmCreate);
   AContext.Connection.IOHandler.ReadStream(FileStream, -1, True);
   FreeAndNil(FileStream);
end;

Open in new window

Author

Commented:
As you see my Source code;

  Naming may confuse you, the server will send the file to the client, but I use a client component on Server Application , and Server component on Client Application, they are only just for sending files.

Now if you can help me with progress bar thing on both Server & Client.

and if there is something like IE download dialog box, it will be great Idea shwoing the Transfer speed, and some information about transfer process.

Thanks in Advance :)

Author

Commented:
another problem with this code,

   After Send Complete, if I Close Server Application, the transferred file on Client machine became 1 KB size. But if I close the client application before server application, size still the same and file transferred is ok.
Oracle dba
CERTIFIED EXPERT
Top Expert 2009
Commented:
Ftp components may be better suited for sending files:
The protocol itself actually gives a good name: File Transfer Protocol

Small sample clientside:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  CopyFile('c:\temp\afile.tmp');
end;

procedure TForm1.CopyFile(aFileName: string);
var Source: TFileStream;
begin
  Source := TFileStream.Create(aFileName, fmOpenRead);
  try
    IdFtp1.Put(Source, ExtractFileName(aFileName));
  finally
    Source.Free;
  end;
end;

procedure TForm1.IdFTP1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin
  ProgressBar1.Position := AWorkCount;
end;

procedure TForm1.IdFTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Int64);
begin
  ProgressBar1.Position := 0;
  ProgressBar1.Max := AWorkCountMax;
end;

Open in new window

Author

Commented:
sorry I never used any FTP component,

so what should I put on Server application, TIdFTP also , or TIdFTPServer? can you please explain further more ?

Author

Commented:
Yes It is, FTP rocks, Thanks:)