How to send a file using HttpClient in C#
By FoxLearn 1/22/2025 2:45:12 AM 5
This can be achieved using HttpClient
and MultipartFormDataContent
. By adding the file into a MultipartFormDataContent
object, you can easily send it as part of the request body.
Sending a Single File
For example, how to send a file using HttpClient
in C#:
var filePath = @"C:\file.png"; using (var multipartFormContent = new MultipartFormDataContent()) { // Load the file and set the file's Content-Type header var fileStreamContent = new StreamContent(File.OpenRead(filePath)); fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png"); // Add the file to the request multipartFormContent.Add(fileStreamContent, name: "file", fileName: "file.png"); // Send the request var response = await httpClient.PostAsync("https://localhost:5000/files/", multipartFormContent); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); }
This code creates a MultipartFormDataContent
object and adds a file (file.png
) to it. The file is sent to a server via an HTTP POST request. The Content-Type
header is set to image/png
, which tells the server the type of the file being sent.
The multipart request looks like this:
POST https://localhost:5000/files/ HTTP/1.1 Host: localhost:5000 Content-Type: multipart/form-data; boundary="43a2ed37-1ab7-3731-b2f4-f84bf159648d" Content-Length: 7279 --43a2ed37-1ab7-3731-b2f4-f84bf159648d Content-Type: image/png Content-Disposition: form-data; name=file; filename=file.png; filename*=utf-8''house.png <bytes>
When adding a file to MultipartFormDataContent
, use the Add()
method:
public void Add(HttpContent content, string name, string fileName);
This method adds the file to the multipart data, and the StreamContent
object will be disposed when MultipartFormDataContent
is disposed.
Sending Form Data with Multiple Fields
Often, you need to send additional data along with the file. You can add extra fields to MultipartFormDataContent
.
For example, if you want to send a title and a user ID along with the file.
var filePath = @"C:\file.png"; using (var multipartFormContent = new MultipartFormDataContent()) { // Add additional fields multipartFormContent.Add(new StringContent("1235"), name: "UserId"); multipartFormContent.Add(new StringContent("Home insurance"), name: "Title"); // Add the file var fileStreamContent = new StreamContent(File.OpenRead(filePath)); fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png"); multipartFormContent.Add(fileStreamContent, name: "file", fileName: "file.png"); // Send the request var response = await httpClient.PostAsync("https://localhost:5000/files/", multipartFormContent); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); }
This sends a multipart request that includes both the title and user ID, as well as the file:
POST https://localhost:5000/files/ HTTP/1.1 Host: localhost:5000 Content-Type: multipart/form-data; boundary="00d235a2-0189-48e1-86d9-0baf70c2879e" Content-Length: 7519 --00d235a2-0189-48e1-86d9-0baf70c2879e Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=UserId 1235 --00d335a2-0389-48e1-85d9-0daf70c2879e Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=Title Home insurance --00d335a2-0389-48e1-85d9-0daf70c2879e Content-Type: image/png Content-Disposition: form-data; name=file; filename=file.png; filename*=utf-8''file.png <bytes>
Sending a File as a Byte Array
If you already have a file in the form of a byte array (perhaps from a database), you can use ByteArrayContent
to send it instead of a file stream:
using (var multipartFormContent = new MultipartFormDataContent()) { // Add the file as a byte array var byteContent = new ByteArrayContent(fileBytesFromDatabase); byteContent.Headers.ContentType = new MediaTypeHeaderValue("image/png"); multipartFormContent.Add(byteContent, name: "file", fileName: "file.png"); // Send the request var response = await httpClient.PostAsync("https://localhost:5000/files/", multipartFormContent); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); }
This will generate a multipart request with the file content being passed as a byte array, rather than as a file stream.
Sending Multiple Files
You can send more than one file in the same request by adding multiple files to the MultipartFormDataContent
.
If the web API expects multiple files under the same field name (e.g., "files"), you can add multiple files using the same name
parameter:
var filePaths = new string[] { @"C:\file1.png", @"C:\file2.png" }; using (var multipartFormContent = new MultipartFormDataContent()) { foreach(var filePath in filePaths) { var fileName = Path.GetFileName(filePath); // Load the file and set the Content-Type header var fileStreamContent = new StreamContent(File.OpenRead(filePath)); fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png"); // Add the file multipartFormContent.Add(fileStreamContent, name: "files", fileName: fileName); } // Send the request var response = await httpClient.PostAsync("https://localhost:5000/files/", multipartFormContent); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); }
This request will look like:
POST https://localhost:5000/files/ HTTP/1.1 Host: localhost:5000 Content-Type: multipart/form-data; boundary="92f8b9da-876f-42ff-8709-84a0b8d0ef08" Content-Length: 14442 --92f8b9da-876f-42ff-8709-84a0b8d0ef08 Content-Type: image/png Content-Disposition: form-data; name=files; filename=file1.png; filename*=utf-8''file1.png <bytes> --92f8b9da-876f-42ff-8709-84a0b8d0ef08 Content-Type: image/png Content-Disposition: form-data; name=files; filename=file2.png; filename*=utf-8''file2.png <bytes>
Alternatively, you can add each file with a unique name parameter, depending on the server’s requirements.
Setting File Content-Type Dynamically
If the file extension is not known in advance, you can dynamically set the Content-Type
based on the file’s extension. Here's an example that uses a dictionary to map file extensions to content types:
var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { [".png"] = "image/png", [".jpg"] = "image/jpeg", [".gif"] = "image/gif" }; var filePath = @"C:\file.png"; var extension = Path.GetExtension(filePath); if (!map.TryGetValue(extension, out string contentType)) { throw new Exception("Can't send this type of file"); } var fileStreamContent = new StreamContent(File.OpenRead(filePath)); fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
By utilizing MultipartFormDataContent
, you can send files along with additional form data or multiple files in a single request. Always ensure that the Content-Type
for the file is set correctly, especially when working with different file types.
- How to Get and send JSON using HttpClient in C#
- How to consume an SSE endpoint using HttpClient in C#
- Sending query strings using HttpClient in C#
- Performance Boost from Reusing HttpClient Connections
- How to change the HttpClient timeout per request in C#
- Handling Redirects with HttpClient in C#
- How to read problem details JSON using HttpClient in C#
- How to Cancel an HttpClient Request in C#