Uploading large files directly via WebClient can lead to high memory consumption because the antire file is loaded into memory before transmission. A more efficient approach uses HttpWebRequest to stream data in chunks, allowing for real-time progress updates and better memory management.
Client-Side Implementation (WinForms)
The following method streams a file to a remote server using multipart/form-data. It updates UI controls like ProgressBar and Label to reflect the transfer speed and percentage.
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
public int SendFileToServer(string url, string localPath, string remoteFileName, ProgressBar progressTracker)
{
int resultStatus = 0;
FileStream fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
BinaryReader fileReader = new BinaryReader(fileStream);
// Generate a unique boundary for the multipart form
string boundaryId = "----" + DateTime.Now.Ticks.ToString("x");
byte[] boundaryEnd = Encoding.ASCII.GetBytes("\r\n--" + boundaryId + "--\r\n");
// Construct the header for the form-data
StringBuilder headerBuilder = new StringBuilder();
headerBuilder.AppendLine("--" + boundaryId);
headerBuilder.AppendLine("Content-Disposition: form-data; name=\"uploadedFile\"; filename=\"" + remoteFileName + "\"");
headerBuilder.AppendLine("Content-Type: application/octet-stream");
headerBuilder.AppendLine();
byte[] headerBytes = Encoding.UTF8.GetBytes(headerBuilder.ToString());
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.AllowWriteStreamBuffering = false; // Stream directly to network
request.Timeout = 300000; // 5 minutes
request.ContentType = "multipart/form-data; boundary=" + boundaryId;
long totalSize = fileStream.Length + headerBytes.Length + boundaryEnd.Length;
request.ContentLength = totalSize;
try
{
progressTracker.Minimum = 0;
progressTracker.Maximum = 100; // Percentage based
progressTracker.Value = 0;
byte[] buffer = new byte[4096];
long bytesSent = 0;
DateTime start = DateTime.Now;
int bytesRead = fileReader.Read(buffer, 0, buffer.Length);
using (Stream requestStream = request.GetRequestStream())
{
// Write Header
requestStream.Write(headerBytes, 0, headerBytes.Length);
bytesSent += headerBytes.Length;
// Write File Content in chunks
while (bytesRead > 0)
{
requestStream.Write(buffer, 0, bytesRead);
bytesSent += bytesRead;
// Update UI
double percentage = (double)bytesSent / totalSize * 100;
progressTracker.Value = Math.Min(100, (int)percentage);
TimeSpan elapsed = DateTime.Now - start;
if (elapsed.TotalSeconds > 0)
{
double speed = (bytesSent / 1024.0) / elapsed.TotalSeconds;
// Update labels (assuming lblSpeed and lblStatus exist)
// lblSpeed.Text = $"{speed:F2} KB/s";
// lblStatus.Text = $"{percentage:F2}% completed";
}
Application.DoEvents(); // Keep UI responsive
bytesRead = fileReader.Read(buffer, 0, buffer.Length);
}
// Write Footer
requestStream.Write(boundaryEnd, 0, boundaryEnd.Length);
}
// Read Server Response
using (WebResponse response = request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string serverResponse = reader.ReadLine();
if (serverResponse == "OK")
{
resultStatus = 1;
}
}
}
catch
{
resultStatus = 0;
}
finally
{
fileReader.Close();
fileStream.Close();
}
return resultStatus;
}
Parameters:
url: The endpoint handling the upload (e.g.,http://localhost/Receiver.aspx).localPath: Full path to the file on disk (e.g.,C:\\Data\\archive.zip).remoteFileName: The name the file should have on the server.progressTracker: A WinFormsProgressBarcontrol.
Server-Side Implementation (ASP.NET WebForms)
Create a page (e.g., Receiver.aspx) and handle the file in the Page_Load event. The server reads the multipart data from Request.Files.
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Files.Count > 0)
{
try
{
HttpPostedFile uploadedFile = Request.Files[0];
string serverPath = Server.MapPath("~/Uploads/") + uploadedFile.FileName;
uploadedFile.SaveAs(serverPath);
Response.Write("OK");
}
catch (Exception)
{
Response.Write("Error");
}
}
}
Configuration
To support large files, update the <httpRuntime> element in web.config. The default limit is usually 4MB.
<configuration>
<system.web>
<httpRuntime maxRequestLength="102400" executionTimeout="300" />
</system.web>
</configuration>
maxRequestLength: Size in KB (e.g., 102400 = 100MB).executionTimeout: Timeout in seconds.
Ensure the IIS site binding also allows to larger request sizes (e.g., via uploadReadAheadSize or maxAllowedContentLength in web.config for IIS 7+).