0

I'm trying to upload a file to the server using WebClient. My code for posting the file is as follows:

        public void UploadMultipart(byte[] file, string filename, string contentType, string url)
    {
        var webClient = new WebClient();
        string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
        webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
        var fileData = Encoding.UTF8.GetString(file);
        var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, filename, contentType, fileData);

        var nfile = webClient.Encoding.GetBytes(package);

        byte[] resp = webClient.UploadData(url, "POST", nfile);
    }

The line Encoding.UTF8.GetString(file) always returns an empty string. I've checked the byte array and it's not empty. I also tried Encoding.UTF8.GetString(file, 0, file.Length) but same result. I've read somewhere that this could be because of improper encoding. If that's the reason then how can I fix it? The file I'm trying to send is a video taken from a camera.

Any help is appreciated.

Ahmed Mujtaba
  • 2,110
  • 5
  • 36
  • 67
  • Can you post some of the contents (hex or int) of the file[] array? BTW, there seems to be some length limit in GetString - https://msdn.microsoft.com/en-us/library/744y86tc(v=vs.110).aspx. Don't know the behaviour if file[] is > 2048 - may as well return empty string :) Check the provided sample in the docs – Kamen Apr 26 '16 at 22:09
  • the debugger is taking excruciatingly long time. dont know why :( – Ahmed Mujtaba Apr 26 '16 at 22:22
  • @Kamen okay so here's what the first byte of the array looks like http://postimg.org/image/jeowmhhoh/ – Ahmed Mujtaba Apr 26 '16 at 22:38
  • Ahmed, `0` byte indicates that it is a `NUL`. Strings end with a `\0` which is the same and why you are getting an empty string based on your screenshot. You should verify how the data is actually being written to that array. As soon as `NUL` is found (encoding specific), it will stop building the string because it thinks it is done and to prevent overflows. – TyCobb Apr 26 '16 at 23:03
  • TyCobb What are those values in the middle? – Ahmed Mujtaba Apr 26 '16 at 23:05
  • No idea. Whatever the data was that was written to the array. I could guess by converting them to UTF or ASCII, but the issue relies on how you're building the file if you are expecting it to be convertible to a string. Are you sure you aren't working with a binary file? You can't convert those to strings. What's the extension of the file name? If it's anything other than something that is plain text, you probably shouldn't be trying to convert it to a string. – TyCobb Apr 26 '16 at 23:08
  • I'm have a video file with the extention .mp4 stored at a location which I'm trying to post to the server. If I can't convert the file to a string then what other way can I send it? – Ahmed Mujtaba Apr 26 '16 at 23:13
  • `.mp4`? You either need to find a way to just send the bytes as they are or you possibly need to Base64 string encode it first and decode it on the other side. I actually cannot answer that portion of the question as I am unsure. But you definitely cannot just convert it to a string =) – TyCobb Apr 26 '16 at 23:16
  • ohh okay. I was hoping that I could it as a multiformdata. I'll have to find another way to do it. – Ahmed Mujtaba Apr 26 '16 at 23:18

1 Answers1

1

Instead of

var fileData = Encoding.UTF8.GetString(file);

you should use

var fileData = Convert.ToBase64String(file, Base64FormattingOptions.InsertLineBreaks);

Due to the second parameter the converter will insert line breaks after every 76 characters in the string representation.

UPDATE:

You may try one of the WebClient.UploadFile() method overloads, like below:

public void UploadFile(string fileName, string url)
{
    var webClient = new WebClient();
    byte[] rawResponse = webClient.UploadFile(url, filename);
    string response = System.Text.Encoding.ASCII.GetString(rawResponse);
    Console.WriteLine(response);
}

UPDATE #2:

You may try the newer API: HttpClient.PostAsync(string, HttpContent)
The string parameter is the Uri.
The HttpContent can be an instance of MultipartFormDataContent.

You can add an instance of ByteArrayContent to the MultipartFormDataContent using its Add() method.

Maybe these will be helpful for your needs.

UPDATE #3:

Here are some possible solutions:

Community
  • 1
  • 1
Gabor
  • 3,021
  • 1
  • 11
  • 20
  • data doesn't convert to a string. i see this on the log instead after that line executes :Error while resolving expression: One or more errors occurred. – Ahmed Mujtaba Apr 26 '16 at 22:59
  • maybe there's something wrong with the data file but it's not corrupted or anything. I'me using File.ReadAllBytes to get the data from the stored location. – Ahmed Mujtaba Apr 26 '16 at 23:00
  • Updated my answer with another possible solution. – Gabor Apr 27 '16 at 00:59
  • That works but I'm trying to send a multipart data. Basically what I'm trying to achieve is send a byte array along with a string. any possible solutions in mind other than what I've implemented above? I preferably wanna use weClient as it's convenient to track the upload progress. – Ahmed Mujtaba Apr 27 '16 at 01:10
  • Thanks for the solution btw – Ahmed Mujtaba Apr 27 '16 at 01:11
  • I don't know why the Encoding always returns an empty string. I have event tried to encode a custom byte array but still same result. What kind of array does it actually encodes? :/ – Ahmed Mujtaba Apr 27 '16 at 01:19
  • Updated my answer with the newer `HttpClient` API. You may try this instead of `WebClient`. – Gabor Apr 27 '16 at 01:26
  • hmm I was thinking of doing that. HttpClient has worked for me before. Any idea how I might be able to track the upload? – Ahmed Mujtaba Apr 27 '16 at 01:33
  • Updated my answer again. :) – Gabor Apr 27 '16 at 01:38