UploadFile with POST values by WebClient
There's nothing built-in that allows you to do that. I have blogged about an extension that you could use. Here are the relevant classes:
public class UploadFile
{
public UploadFile()
{
ContentType = "application/octet-stream";
}
public string Name { get; set; }
public string Filename { get; set; }
public string ContentType { get; set; }
public Stream Stream { get; set; }
}
public byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
{
var request = WebRequest.Create(address);
request.Method = "POST";
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
request.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
using (var requestStream = request.GetRequestStream())
{
// Write the values
foreach (string name in values.Keys)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
// Write the files
foreach (var file in files)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
file.Stream.CopyTo(requestStream);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
}
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var stream = new MemoryStream())
{
responseStream.CopyTo(stream);
return stream.ToArray();
}
}
and now you could use it in your application:
using (var stream = File.Open(dumpPath, FileMode.Open))
{
var files = new[]
{
new UploadFile
{
Name = "file",
Filename = Path.GetFileName(dumpPath),
ContentType = "text/plain",
Stream = stream
}
};
var values = new NameValueCollection
{
{ "client", "VIP" },
{ "name", "John Doe" },
};
byte[] result = UploadFiles(address, files, values);
}
Now in your PHP script you could use the $_POST["client"]
, $_POST["name"]
and $_FILES["file"]
.
WebClient Upload file with variables posted
you can add a header like this
webClient.Headers.Add("OurSecurityHeader", "encryptedvalue");
On the php side, you can use this to read headers:
How do I read any request header in PHP
File upload via multipart-form-data using WebClient in C#
If you need both files
and objects in the payload you can use a multipart
form like this:
Form
<form id="createForm" method="post" enctype="multipart/form-data" action="http://localhost:5000/api/send">
<input type="text" name="Field1" id="field1" />
<input type="text" name="Field2" id="field2" />
<input type="file" id="bulk" name="Bulk" required />
</form>
POCO
class MyClass
{
public string Field1{get;set;}
public string Field2{get;set;}
}
Controller
In the controller you can access the files using Request.Form.Files
which gives you a collection with all your uploaded files.Then you can read your file(s) using a StreamReader
like i do below:
[HttpPost]
[Route("api/send")]
[DisableRequestSizeLimit]
public async Task<long> CreateAsync(MyClass obj) {
{
var file=this.Request.Form.Files[0]; //there's only one in our form
using(StreamReader reader=new StreamReader(file))
{
var data=await reader.ReadToEndAsync();
Console.WriteLine("File Content:"+data);
Console.WriteLine("{ Field1 :"+obj.Field1.ToString()+",Field2:"+obj.Field2.ToString()+"}");
}
}
Caution
Take care when dealing with multipart
since you will also need to specify the maximum
size of a segment.
That is done in the Startup
:
public void ConfigureServices(IServiceCollection services) {
services.Configure<FormOptions>(options => {
options.ValueCountLimit = 200;
options.ValueLengthLimit = int.MaxValue;
options.MultipartBodyLengthLimit = long.MaxValue;
});
}
or like i did it directly in the Controller
-s method , by decorating it with [DisableRequestSizeLimit]
attribute.
Related Topics
What Does Synchronizationcontext Do
Specified Argument Was Out of the Range of Valid Values. Parameter Name: Site
Is There a Faster Way to Scan Through a Directory Recursively in .Net
Opening a Folder in Explorer and Selecting a File
Prevent Property from Being Serialized in Web API
How to Get First Record in Each Group Using Linq
Debugging Automatic Properties
Dependent Dll Is Not Getting Copied to the Build Output Folder in Visual Studio
Injecting Dependencies into ASP.NET MVC 3 Action Filters. What's Wrong with This Approach
How to Multi-Target a .Net Core Class Library with Csproj
How to Verify Text Is Bold Using Selenium on an Angular Website with C#
Simple iOS Bluetooth Data Transmission Using Unity
Making a Private Method Public to Unit Test It...Good Idea
How to Set Up a Web API Controller for Multipart/Form-Data
Performance Tests of Serializations Used by Wcf Bindings