how to send multiple images from a specific folder from client to server. I managed to send only one image! i used this code
client code
fn := 'C:\Documents and Settings\admin\Desktop\11/65474.jpg';
fs := TFileStream.Create(fn, fmOpenRead);
Host := Edit1.Text;
idTCPClient1.Connect;
IdTCPClient1.IOHandler.Write(fs);
Server Code
procedure TForm3.IdTCPServer1Execute(AContext: TIdContext);
var
fs: TFileStream;
begin
fs := TFileStream.Create('C:\Documents and Settings\Admin\Desktop\pic\.png', fmCreate);
AContext.Connection.IOHandler.ReadStream(fs, -1, True);
end;
the idea is to send all imges in folder to a client from one tcpserver.idTCPCLient plz help?? im sorry for noob question.
Your calls to TIdIOHandler.Write(TStream)
and TIdIOHandler.ReadStream()
are mismatched.
By default, ReadStream()
expects the stream size to be sent before the stream data. When AByteCount
is -1 and AReadUntilDisconnect
is False (the default parameter values), ReadStream()
reads the first 4 or 8 bytes (depending on the TIdIOHandler.LargeStream
property) to know how many bytes to read into the TStream
. However, you are setting AReadUntilDisconnect
to True instead, so AByteCount
is ignored, and ReadStream()
will not exit until the client disconnects from the server. That is the wrong functionality to use if you need to receive more than one stream (or anything else after the first stream, for that matter).
By default, the AWriteByteCount
parameter of Write(TStream)
is False, so it does not send the stream size. When AWriteByteCount
is set to True instead, Write()
sends the stream size using 4 or 8 bytes (depending on the TIdIOHandler.LargeStream
property) before then sending the stream content.
So, you are telling the client NOT to send the stream size, and telling the server to IGNORE the stream size (OK for the example you showed, but not OK for your intended goal), but you are also telling the server to WAIT until the client disconnects to signal the end of the stream, but the client is not disconnecting after sending the stream.
Try something more like this instead:
idTCPClient1.Host := Edit1.Text;
idTCPClient1.Connect;
...
for fn in TDirectory.GetFiles('C:/1/') do
begin
fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
try
IdTCPClient1.IOHandler.WriteLn(ExtractFileName(fn));
IdTCPClient1.IOHandler.Write(fs, 0, True);
end;
fs.Free;
end;
end;
...
idTCPClient1.Disconnect;
procedure TForm3.IdTCPServer1Execute(AContext: TIdContext);
var
fn: string;
fs: TFileStream;
begin
fn := 'some base path\' + ExtractFileName(AContext.Connection.IOHandler.ReadLn);
fs := TFileStream.Create(fn, fmCreate);
try
try
AContext.Connection.IOHandler.ReadStream(fs, -1, False);
finally
fs.Free;
end;
except
DeleteFile(fn);
raise;
end;
end;
Of course, there is a very bare bones protocol. A more flexible protocol would use a command/response model so a client can send different types of commands other than file transfers, a client can ask permission to send a file before actually sending it, the server can send a confirmation if a file was successfully received or not, etc.