7

I have a requirement to post binary file of size 100MB data in the format of either JSON or byte array to Web API 1.1. My client application is C# winforms application with x32 bit architecture. Where as I want to perform reading binary file from this client application and send this binary file byte array to Web API.

Current implementation in my winforms application is as below

var sFile = @"C"\binary.zip";
var mybytearray = File.ReadAllBytes(sFile);
var webRequest =
                (HttpWebRequest)WebRequest.Create("http://localhost/filewriter");
webRequest.ContentType = "text/plain";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.AllowWriteStreamBuffering = true;
webRequest.Timeout = 100000;
webRequest.Headers.Add("fileName", Path.GetFileName(sFile));
webRequest.ContentLength = mybytearray.Length;

using (var dataStream = new StreamWriter(webRequest.GetRequestStream()))
      dataStream.Write(mybytearray);

using (var response = webRequest.GetResponse())
{
    if(response.StatusCode = HttpStatusCode.Ok;
         return true;
}

below is written at my Web api method

[HttpPost]
public HttpResponseMessage filewriter(byte[] binaryData)
{
    using (FileStream binaryFileStream = new FileStream("C:\\myNewFile.zip", FileMode.Create, FileAccess.ReadWrite))
          {
              binaryFileStream.Write(binaryData, 0, binaryData.Length);
          }
}

As you can see, in above code I was not able to send byte array to web api method filewriter. Am I missing something that should work in this case.

Other way as I said I was tried same but instead of byte array with Json one as below

var sFile = @"C"\binary.zip";   
var mybytearray = File.ReadAllBytes(sFile);
var mymodel = new model
{
    fileName = sFile,
    binaryData = mybytearray
};

var jsonResendObjects = JsonConvert.SerializeObject(mymodel);
var webRequest = (HttpWebRequest)WebRequest.Create("http://localhost/filewriter");
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.AllowWriteStreamBuffering = true;
webRequest.Timeout = 100000;
webRequest.Headers.Add("fileName", Path.GetFileName(sFile));
webRequest.ContentLength = jsonResendObjects.Length;
byte[] responseData = null;

webRequest.AllowWriteStreamBuffering = true;
using (var dataStream = new StreamWriter(webRequest.GetRequestStream()))
    dataStream.Write(jsonResendObjects);

On web api side

[HttpPost]
public HttpResponseMessage filewriter([FromBody]model mymodel)
{
    using (FileStream binaryFileStream = new FileStream("C:\\myNewFile.zip", FileMode.Create, FileAccess.ReadWrite))
          {
              binaryFileStream.Write(mymodel.binarydata, 0, binaryDatabinarydat.Length);
          }
}
CSharpDev
  • 370
  • 1
  • 7
  • 28
  • stefan, this is not to upload file, I want to upload bytes and on web api method this should write bytes to file – CSharpDev Sep 26 '18 at 11:43
  • Did you check the solution from [link](https://stackoverflow.com/questions/23518817/send-byte-array-by-http-post-in-store-app), I think tis is very similar – Daniel W. Sep 26 '18 at 11:43

1 Answers1

10

According to me, it would be easy to use base64 encoding for communication.

If you want to do so

First, convert your file to byte[] and then to base64 string

Like this:

byte[] bytes = File.ReadAllBytes("path");
string file = Convert.ToBase64String(bytes);
// You have base64 Data in "file" variable

On your WebAPI Endpoint accept string

[HttpPost]
public HttpResponseMessage filewriter(string fileData)
{
}

Then convert your base64 string back to byte[] and write it to file or whatever you want to do with that.

Like This:

// put your base64 string in b64str
Byte[] bytes = Convert.FromBase64String(b64Str);
File.WriteAllBytes(path, bytes);

And you can Compress your string Using GZIP Like this

public static void CopyTo(Stream src, Stream dest) {
    byte[] bytes = new byte[4096];

    int cnt;

    while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) {
        dest.Write(bytes, 0, cnt);
    }
}

public static byte[] Zip(string str) {
    var bytes = Encoding.UTF8.GetBytes(str);

    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream()) {
        using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
            //msi.CopyTo(gs);
            CopyTo(msi, gs);
        }

        return mso.ToArray();
    }
}

public static string Unzip(byte[] bytes) {
    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream()) {
        using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
            //gs.CopyTo(mso);
            CopyTo(gs, mso);
        }

        return Encoding.UTF8.GetString(mso.ToArray());
    }
}

Reference:-

Convert file to base64 and back

GZip Compression

Mihir Dave
  • 3,954
  • 1
  • 12
  • 28
  • Mihir, what if we convert 100 MB file bytes to base64, what I know is base64 will consume more memory and my winforms client application is written to have 32 bit architecture and it is already loaded with other components. As you know OS will allow only 1.8GB to 32 bit applications. – CSharpDev Sep 26 '18 at 11:58
  • @CSharpDev Have you used Gzip Compression? it could do wonders. recent browser and server use this technology for compression. check my updated answer, give a shot to compression and see it for your self how much that effect to your file size, this is basically transferring your file after zipping it. – Mihir Dave Sep 26 '18 at 12:01
  • @CSharpDev if you not make the base64 conversion that would be done by the http protocol used for transportation, because http is not able to transport binary data without converting to a format like base 64. – Daniel W. Sep 26 '18 at 17:48
  • Well Said @DanielW. – Mihir Dave Sep 27 '18 at 08:40
  • I just felt the necessity to say that you saved my life :) – gabriel.santos Dec 10 '19 at 15:46
  • @gabriel.santos Glad this answer helped you. – Mihir Dave Dec 11 '19 at 10:06