0

I try to mirror images on my own image hoster, which contains a simple API that accepts default form data uploads like this:

-----------------------------149841124823007
Content-Disposition: form-data; name="file"; filename="ZMVdEwM.png"
Content-Type: image/png
<Binary image data...>

This upload was tested using a simple html form and works well. Now I want to use this API in an .NET Core Standard application. Found different examples:

string url = "https://i.stack.imgur.com/uwGdv.png";
var client = new HttpClient();
var imageData = client.GetByteArrayAsync(url).Result;

var content = new MultipartFormDataContent($"-----------------------------{DateTime.Now.Ticks}");
content.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
string fileName = new Uri(url).LocalPath.Replace("/", "");
content.Add(new ByteArrayContent(imageData), "file", fileName);
var postResp = client.PostAsync("https://my-image-hoster/api.php", content).Result;
string resp = postResp.Content.ReadAsStringAsync().Result;
Console.WriteLine(resp);

I'm downloading the test image https://i.stack.imgur.com/uwGdv.png as byte array and try to build the same form-data upload. But it fails here on my api:

if (!isset($_FILES['file'])) {
    echo json_encode(array('errorcode' => 'no_image_transfered'));
}

While investigation the problem, I inspected the MultipartFormDataContent instance called content since it's responsible for building the request body. It shows a ContentDisposition property containing the file name twice: The first one is correct, but the second one looks maleformed:

enter image description here

What's wrong with my POST request?

Community
  • 1
  • 1
Lion
  • 16,606
  • 23
  • 86
  • 148

1 Answers1

0

Found out that MultipartFormDataContent.Headers.ContentType is the value of the HTTP header:

Content-Type: multipart/form-data; boundary=--------------149841124823007

This was taken from the example, which breaks my API since it expects multipart/form-data. So it's better to dismiss the type, unless your API checks the provided file type in $_FILES['file'][0]['type'] because this is empty. The type came from the body:

Content-Disposition: form-data; name="file"; filename="ZMVdEwM.png"
Content-Type: image/png <--- type

Since it's a value provided by the client, we shouldn't trust this data and fetch the mime-type on the server side. If you have an API that checks this value (and no influence on the API itself) just set it for the body like this:

content.ElementAt(0).Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");

Otherwise if you're fine with a multipart/form-data upload that doesn't contain the mime type, do your upload like this:

string url = "https://i.imgur.com/0acC9nr.png";
var client = new HttpClient();
var imageData = client.GetByteArrayAsync(url).Result;

var content = new MultipartFormDataContent();
string fileName = new Uri(url).LocalPath.Replace("/", "");
content.Add(new ByteArrayContent(imageData), "file", fileName);
// Optionally when the Content-Type body field is required
// content.ElementAt(0).Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
var postResp = client.PostAsync("https://my-image-hoster/api.php", content).Result;
var resp = postResp.Content.ReadAsStringAsync().Result;
Lion
  • 16,606
  • 23
  • 86
  • 148