Hallo,
Du musst dem Server mitteilen, wie groß die Datei ist, die da verschickt wird!
Ich habe das so gelöst:
Delphi-Quellcode:
...
IdTcpClient1.WriteInteger(4);
IdTcpClient1.WriteLn(sMsgToSvr);
IdTcpClient1.WriteInteger(SendSize);
idTCPClient1.OpenWriteBuffer;
idTcpClient1.WriteStream(fs, False, False, SendSize);
idTCPClient1.CloseWriteBuffer;
...
Erklärung:
In der ersten Zeile wird per Kommando dem Server mitgeteilt, was er machen sollen, ähnlich dem '!' in Deinem Code.
Danach kommt der Dateiname (sMsgToSvr), danach (wichtig!) die Dateigröße (SendSize) ...
dann der Empfang der Datei:
Delphi-Quellcode:
...
if Msg[1] = '#' then //send files
begin
msg2 := Copy(Msg, 2, Length(Msg));
if FileExists(ProgDir + Msg2) then
DeleteFile(ProgDir + Msg2);
ftmpStream := TFileStream.Create(ProgDir + Msg2, fmCreate or fmShareDenyNone);
try
try
//while IdTCPClient1.connected do
FileSize := IdTCPClient1.ReadInteger();
IdTCPClient1.ReadStream(fTmpStream, FileSize, False); //-1,true);
Log(100, 'File ' + Msg2 + ' with ' + IntToStr(FileSize) + ' kbs received!');
PostMessage(avatar, 'File ' + Msg2 + ' with ' + IntToStr(FileSize) + ' kbs received!');
Application.ProcessMessages;
except
Log(101, 'Error on filetransfer!');
exit;
end;
finally
FreeAndNil(fTmpStream);
end;
end;
...
Auch hier wird erst wieder die Größe der zu empfangenden Datei festgestellt...
Ach ja, hier die Behandlung der Datei durch den Server und den Versand an alle Clients (im TCPServer.Execute):
Delphi-Quellcode:
Cmd := AThread.Connection.ReadInteger;
if cmd = 4 then
begin
try
try
Msg := AThread.Connection.ReadLn;
FileName := Msg;
CS := TCriticalSection.Create;
CS.Enter;
sMsgToClt := '#' + FileName;
ts := TMemoryStream.Create;
FileSize := AThread.Connection.ReadInteger();
AThread.Connection.ReadStream(ts, FileSize, False);
Log(Format('Getting client upload %5d, %s', [FileSize, FileName]));
List := TcpServer.Threads.LockList;
try
for Count := 0 to List.Count -1 do
try
TIdPeerThread(List.Items[Count]).Connection.WriteLn(sMsgToClt);
TIdPeerThread(List.Items[Count]).Connection.WriteInteger(FileSize);
TIdPeerThread(List.Items[Count]).Connection.OpenWriteBuffer;
TIdPeerThread(List.Items[Count]).Connection.WriteStream(ts, True, False, FileSize);
TIdPeerThread(List.Items[Count]).Connection.CloseWriteBuffer;
Log('File ' + ExtractFileName(FileName) + ' sent to clients!');
except
TIdPeerThread(List.Items[Count]).Stop;
Log('Error while sending file to clients!');
end;
finally
TcpServer.Threads.UnlockList;
CS.Leave;
end;
except
ShowMessage('Error');
Log('Error on getting file');
end;
finally
ts.free;
end;
Edit:
Ein wenig ausführlicher habe ich das Ganze nun in folgenden Thread ausgeführt:
Beispiel zum Versenden von Dateien mit Indy