TsgcWebSocketServer_HTTPAPI | Send File Response

Use the FileName property of THttpServerResponse object if you want to send a filename as a response to a HTTP request.

 


void OnHTTPRequest(TsgcWSConnection_HTTPAPI aConnection,
	THttpServerRequest aRequestInfo,
	ref THttpServerResponse aResponseInfo)
{
  if (aRequestInfo.Method == "GET")
  {
    if (aRequestInfo.Document == "/test.zip")
	{
	  aResponseInfo.ResponseNo = 200;
	  aResponseInfo.FileName = "c:\download\test.zip";
	  aResponseInfo.ContentType = "application/zip";
	}
	else
	{
	  aResponseInfo.ResponseNo = 404;
	}
  }
  else
  {  
    aResponseInfo.ResponseNo = 500;
  }
}

Resumable Downloads

An HTTP 206 Partial Content response is used when a server is fulfilling a request for a specific portion (range) of a resource, instead of sending the entire file. This is commonly used for resumable downloads, media streaming, and large file transfers. 

How it works:

 

Client Requests a Partial Resource: The client (browser, downloader, or media player) sends a Range header specifying the byte range it wants. Example request:

 

GET /video.mp4 HTTP/1.1
Host: example.com
Range: bytes=1000-5000

 

This requests bytes 1000 to 5000 of video.mp4.

 

Server Responds with HTTP 206: If the server supports range requests, it responds with 206 Partial Content and includes a Content-Range header. Example response:

 

HTTP/1.1 206 Partial Content
Content-Range: bytes 1000-5000/1000000
Content-Length: 4001
Content-Type: video/mp4

 

The Content-Range header shows:

 

The range served (1000-5000)

The total size of the file (1000000 bytes).

The Content-Length header is the size of the returned portion (4001 bytes).

 

Client Can Request More Chunks:

The client can send multiple requests for different parts.

This enables resumable downloads and efficient streaming.

 


    [HttpGet("download")]
    public async Task<IActionResult> DownloadFile()
    {
        string filePath = "test.pdf";
        if (!System.IO.File.Exists(filePath))
        {
            return NotFound();
        }
        FileInfo fileInfo = new FileInfo(filePath);
        long fileSize = fileInfo.Length;
        string contentType = "application/pdf";
        HttpContext.Request.Headers.TryGetValue("Range", out var rangeHeader);
        
        if (!string.IsNullOrEmpty(rangeHeader))
        {
            long start, end;
            string[] range = rangeHeader.ToString().Replace("bytes=", "").Split('-');
            start = string.IsNullOrEmpty(range[0]) ? 0 : long.Parse(range[0]);
            end = string.IsNullOrEmpty(range[1]) ? fileSize - 1 : long.Parse(range[1]);
            if (end >= fileSize)
                end = fileSize - 1;
            long contentLength = end - start + 1;
            
            Response.StatusCode = (int)HttpStatusCode.PartialContent;
            Response.Headers["Content-Range"] = $"bytes {start}-{end}/{fileSize}";
            Response.Headers["Accept-Ranges"] = "bytes";
            byte[] buffer = new byte[contentLength];
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                fs.Seek(start, SeekOrigin.Begin);
                await fs.ReadAsync(buffer, 0, buffer.Length);
            }
            return File(buffer, contentType);
        }
        return File(System.IO.File.OpenRead(filePath), contentType);
    }