Uploadfile with Post Values by Webclient

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



Leave a reply



Submit