I use this code to send a file to a client.
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
hFile : THandle;
FileBuff : array [0..1023] of byte;
dwRead : DWORD;
Recieved : String;
begin
Recieved := Athread.Connection.ReadLn;
if Recieved = 'FILE' then begin
Memo1.Lines.Add('Sending File...');
hFile := CreateFileW('FILE.bin',
GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile = INVALID_HANDLE_VALUE then exit;
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
while true do begin
ReadFile(hFile, FileBuff[0], 1024, dwRead, nil);
if dwRead <= 0 then break;
Athread.Connection.WriteBuffer(FileBuff[0], dwRead);
end;
CloseHandle (hFile);
Athread.Connection.Disconnect;
end;
end;
This works like a charm but if the client disconnects while the file is sending, Indy terminates the Execute Thread immediately so the filehandle is still open! Is there a way to close the filehandle after the client disconnects?
Thank you for your help.
Your code has three problems in it:
1) accessing the TMemo directly is not thread-safe, so it can cause deadlocks and/or crashed. UI access must be done in the context of the main thread only. You can use Indy's
TIdSync
orTIdNotify
class to safely access the UI from server events.2) like RRUZ mentioned, you are not protecting the file handle from exceptions. If an exception is raised, like when a client disconnects, you are not closing the file handle.
3) you are opening the file using a relative path. Always use absolute paths to ensure the correct file is used.
Try this:
Alternatively, you can pass the filename to Indy and let it manage the file for you: