Custom Protocol — Files
File-transfer custom subprotocol — chunked, resumable upload and download over WebSocket with progress notifications.
File-transfer custom subprotocol — chunked, resumable upload and download over WebSocket with progress notifications.
This protocol allows sending files using binary WebSocket transport. It can handle big files with a low memory usage.
TsgcWSPClient_Files| Component class | TsgcWSPClient_Files (unit sgcWebSocket_Protocols, ancestor TsgcWSProtocol_Files_Client in unit sgcWebSocket_Protocol_Files_Client) |
| Frameworks | VCL, FireMonkey, Lazarus / FPC, .NET |
| Platforms | Windows, macOS, Linux, iOS, Android |
The principal published / public properties used to configure and drive the component. Consult the online help for the full list.
Client | WebSocket client component used as transport for the Files subprotocol. |
Broker | Optional broker component that forwards file-protocol traffic through a shared client transport. |
Files | File-transfer settings collection covering buffer size, save directory and QoS. |
Guid | Identifier used by the server to route file-protocol traffic to this client instance. |
Version | Read-only sgcWebSockets library version string. |
The principal public methods exposed by the component.
Subscribe() | Subscribes this client to a channel so it receives file-protocol notifications published on it. |
UnSubscribe() | Cancels a previous Subscribe so the client no longer receives messages from the channel. |
SendFile() | Uploads a file to the server in fragmented chunks with configurable QoS. |
WriteData() | Sends a plain text message to the server over the Files subprotocol. |
The component exposes the following published events; consult the online help for full event-handler signatures.
OnBinary | Fires when a raw binary frame arrives through the Files subprotocol transport. |
OnConnect | Fires after the WebSocket handshake completes and the Files subprotocol is ready to transfer files. |
OnDisconnect | Fires when the transport connection drops; the subprotocol stops its QoS timer and optionally clears the pending streams. |
OnError | Fires for transport-level errors reported by the underlying sgcWebSocket client. |
OnException | Fires when an unhandled exception is raised inside the subprotocol worker or QoS timer thread. |
OnFileBeforeSent | Fires just before the file header leaves the client, letting you inspect or tweak the outgoing TsgcWSMessageFile. |
OnFileReceived | Fires when an incoming file has been fully received and persisted to disk. |
OnFileReceivedAuthorization | TsgcWSPClient_Files › Events › OnFileReceivedAuthorization |
OnFileReceivedError | property OnFileReceivedError: TsgcWSFileErrorEvent; // TsgcWSFileErrorEvent = procedure(Connection: TsgcWSConnection; const aMessage: TsgcWSMessageFile; const Error: String) of object __property TsgcW... |
OnFileReceivedFragment | Fires every time a new fragment of an incoming file has been written to disk; ideal for progress indicators. |
OnFileSent | Fires when the server confirms that a file has been fully received. |
OnFileSentAcknowledgment | Fires when the server acknowledges processing of an outbound file fragment under qosLevel1 or qosLevel2. |
OnFileSentError | Fires when the upload of a file fails either locally or after a rejection from the server. |
OnFileSentFragmentRequest | Fires each time the client is about to send a new outbound file fragment; ideal for upload progress and cancellation. |
OnFragmented | Fires for every fragmented WebSocket frame passing through the Files subprotocol transport. |
OnMessage | Fires when a plain text message arrives inside a Files subprotocol envelope. |
OnRawMessage | Fires with the untouched incoming text before the subprotocol parses it; set Handled to stop default processing. |
OnSubscription | Fires when the server confirms a channel subscription requested with Subscribe. |
OnUnSubscription | Fires when the server confirms that a channel subscription has been cancelled. |
Drop the component on a form, configure the properties below and activate it. The snippet that follows shows the typical Files subprotocol client and server pair configuration.
// --- server side oServer := TsgcWebSocketServer.Create(nil); oServer.Port := 80; oServerFiles := TsgcWSPServer_Files.Create(nil); oServerFiles.Server := oServer; oServerFiles.Files.SaveDirectory := 'C:\server\inbox\'; oServer.Active := True; // --- client side oClient := TsgcWebSocketClient.Create(nil); oClient.Host := '127.0.0.1'; oClient.Port := 80; oClientFiles := TsgcWSPClient_Files.Create(nil); oClientFiles.Client := oClient; oClientFiles.Files.BufferSize := 8192; oClientFiles.Files.SaveDirectory := 'C:\inbox\'; oClientFiles.Files.QoS.Level := qosLevel1; oClientFiles.OnFileSent := OnFileSentEvent; oClientFiles.OnFileReceived := OnFileReceivedEvent; oClient.Active := True; oClientFiles.Subscribe('files'); oClientFiles.SendFile('C:\data\report.pdf');
// --- server side oServer = new TsgcWebSocketServer(this); oServer->Port = 80; oServerFiles = new TsgcWSPServer_Files(this); oServerFiles->Server = oServer; oServerFiles->Files->SaveDirectory = "C:\\server\\inbox\\"; oServer->Active = true; // --- client side oClient = new TsgcWebSocketClient(this); oClient->Host = "127.0.0.1"; oClient->Port = 80; oClientFiles = new TsgcWSPClient_Files(this); oClientFiles->Client = oClient; oClientFiles->Files->BufferSize = 8192; oClientFiles->Files->SaveDirectory = "C:\\inbox\\"; oClientFiles->Files->QoS->Level = qosLevel1; oClientFiles->OnFileSent = OnFileSentEvent; oClientFiles->OnFileReceived = OnFileReceivedEvent; oClient->Active = true; oClientFiles->Subscribe("files"); oClientFiles->SendFile("C:\\data\\report.pdf");
// --- server side oServer = new TsgcWebSocketServer(); oServer.Port = 80; oServerFiles = new TsgcWSPServer_Files(); oServerFiles.Server = oServer; oServerFiles.Files.SaveDirectory = @"C:\server\inbox\"; oServer.Active = true; // --- client side oClient = new TsgcWebSocketClient(); oClient.Host = "127.0.0.1"; oClient.Port = 80; oClientFiles = new TsgcWSPClient_Files(); oClientFiles.Client = oClient; oClientFiles.Files.BufferSize = 8192; oClientFiles.Files.SaveDirectory = @"C:\inbox\"; oClientFiles.Files.QoS.Level = TwsQoS.qosLevel1; oClientFiles.OnFileSent += OnFileSentEvent; oClientFiles.OnFileReceived += OnFileReceivedEvent; oClient.Active = true; oClientFiles.Subscribe("files"); oClientFiles.SendFile(@"C:\data\report.pdf");
Each scenario shows the configuration and method calls needed to drive the component through a specific real-world flow. Every identifier below is taken from the component declaration shipped with the library.
Every incoming transfer raises OnFileReceivedAuthorization before a single byte is written. The handler receives the proposed file name in a var parameter, so you can rename the file, and an Accept flag you can clear to refuse the transfer. Progress arrives on OnFileReceivedFragment, completion on OnFileReceived, and failures on OnFileReceivedError.
procedure TForm1.OnFileReceivedAuthorizationEvent(Connection: TsgcWSConnection; const aMessage: TsgcWSMessageFile; var aFileName: string; var Accept: Boolean); begin Accept := ExtractFileExt(aMessage.FileName) <> '.exe'; aFileName := 'received_' + aMessage.FileName; end; procedure TForm1.OnFileReceivedFragmentEvent(Connection: TsgcWSConnection; const aMessage: TsgcWSMessageFile; var Cancel: Boolean); begin ProgressBar1.Position := Round(aMessage.FilePosition / aMessage.FileSize * 100); end; procedure TForm1.OnFileReceivedEvent(Connection: TsgcWSConnection; const aMessage: TsgcWSMessageFile); begin DoLog('received ' + aMessage.FileName); end;
void __fastcall TForm1::OnFileReceivedAuthorizationEvent( TsgcWSConnection *Connection, TsgcWSMessageFile *aMessage, String &aFileName, bool &Accept) { Accept = ExtractFileExt(aMessage->FileName) != ".exe"; aFileName = "received_" + aMessage->FileName; } void __fastcall TForm1::OnFileReceivedFragmentEvent( TsgcWSConnection *Connection, TsgcWSMessageFile *aMessage, bool &Cancel) { ProgressBar1->Position = (int)(aMessage->FilePosition * 100 / aMessage->FileSize); } void __fastcall TForm1::OnFileReceivedEvent(TsgcWSConnection *Connection, TsgcWSMessageFile *aMessage) { DoLog("received " + aMessage->FileName); }
void OnFileReceivedAuthorizationEvent(TsgcWSConnection Connection, TsgcWSMessageFile MessageFile, ref string FileName, ref bool Accept) { Accept = Path.GetExtension(MessageFile.FileName) != ".exe"; FileName = "received_" + MessageFile.FileName; } void OnFileReceivedFragmentEvent(TsgcWSConnection Connection, TsgcWSMessageFile MessageFile, ref bool Cancel) { progressBar1.Value = (int)(MessageFile.FilePosition * 100 / MessageFile.FileSize); } void OnFileReceivedEvent(TsgcWSConnection Connection, TsgcWSMessageFile MessageFile) { DoLog("received " + MessageFile.FileName); }
Files.BufferSize sets the size of every fragment, so a large file is streamed in pieces rather than held in memory. Files.QoS.Level set to qosLevel1 or qosLevel2 makes the peer acknowledge each fragment, and Interval and Timeout control the retry cadence. The SendFile overload that takes an explicit size and QoS lets you override the component defaults for one transfer.
oClientFiles.Files.BufferSize := 65536; oClientFiles.Files.QoS.Level := qosLevel1; oClientFiles.Files.QoS.Interval := 1000; oClientFiles.Files.QoS.Timeout := 30000; oClientFiles.Files.ClearSentStreamsOnDisconnect := False; // per-transfer override: file name, chunk size, QoS, data, file id oClientFiles.SendFile('C:\data\archive.zip', 65536, qosLevel1, '', 'archive-1');
oClientFiles->Files->BufferSize = 65536; oClientFiles->Files->QoS->Level = qosLevel1; oClientFiles->Files->QoS->Interval = 1000; oClientFiles->Files->QoS->Timeout = 30000; oClientFiles->Files->ClearSentStreamsOnDisconnect = false; oClientFiles->SendFile("C:\\data\\archive.zip", 65536, qosLevel1, "", "archive-1");
oClientFiles.Files.BufferSize = 65536; oClientFiles.Files.QoS.Level = TwsQoS.qosLevel1; oClientFiles.Files.QoS.Interval = 1000; oClientFiles.Files.QoS.Timeout = 30000; oClientFiles.Files.ClearSentStreamsOnDisconnect = false; oClientFiles.SendFile(@"C:\data\archive.zip", 65536, TwsQoS.qosLevel1, "", "archive-1");
On the server side SendFile takes the target connection Guid as its first argument, so you can push a file to one client. BroadcastFile sends the same file to every connected client, optionally narrowed to a channel.
// push to one client, identified by its connection Guid oServerFiles.SendFile(Connection.Guid, 'C:\server\out\manual.pdf'); // push to everyone oServerFiles.BroadcastFile('C:\server\out\manual.pdf');
oServerFiles->SendFile(Connection->Guid, "C:\\server\\out\\manual.pdf"); oServerFiles->BroadcastFile("C:\\server\\out\\manual.pdf");
oServerFiles.SendFile(Connection.Guid, @"C:\server\out\manual.pdf"); oServerFiles.BroadcastFile(@"C:\server\out\manual.pdf");
Every external claim links back to a primary source. The online-help references decode the canonical deep-link the company maintains for this component.
Demos\02.WebSocket_Protocols\02.Send_Receive_Files_Protocol
.net\demos\02.WebSocket_Protocols\02.Send_Receive_Files_Protocol