Issue submitting multipart/form data POST request using UnityWebRequest and IMultipartFormSection
I'm developing several apps which require interaction with a RESTful API via HTTP GET and POST requests. I had been successfully using UniWeb for these requests, but I am attempting to remove third party dependancies from my projects. I have been replacing the UniWeb calls calls with the new UnityWebRequest feature (Unity 5.4.0f3).
I have been having trouble building POST requests submitting multipart form data containing binary files. While I can get it to work using WWWForm, when I attempt to update to IMultipartFormSection implementations for future-proofing I consistently receive 400 errors from the server, saying that required fields are missing. When I look at the requests using WireShark, I can see that the fields are being sent as intended. However the Content-Type is being set as application/x-www-form-urlencoded. If I override this to multipart/form-data, I receive the same response from the server.
If anyone can point out what I'm doing wrong, or whether it is an issue in the UnityWebRequest implementation, I'd much appreciate it!
Here is the code where I construct and send the request, an example response, and the contents of an example multipart form exported from WireShark.
Code
List<IMultipartFormSection> form = new List<IMultipartFormSection>();
form.Add(new MultipartFormDataSection("device_id", SBSettings.DeviceId));
form.Add(new MultipartFormDataSection("version", SBSettings.Version));
form.Add(new MultipartFormDataSection("auth_token", MTSettings.AuthToken));
if (!string.IsNullOrEmpty(currentItem.subject))
form.Add(new MultipartFormDataSection("subject", currentItem.subject));
form.Add(new MultipartFormDataSection("username", currentItem.userName));
if (MTGeoIP.LocationData.latitude != 0)
form.Add(new MultipartFormDataSection("user_lat", MTGeoIP.LocationData.latitude.ToString()));
if (MTGeoIP.LocationData.longitude != 0)
form.Add(new MultipartFormDataSection("user_lng", MTGeoIP.LocationData.longitude.ToString()));
if (!string.IsNullOrEmpty(MTGeoIP.LocationData.countryCode))
form.Add(new MultipartFormDataSection("country", MTGeoIP.LocationData.countryCode));
form.Add(new MultipartFormFileSection("audio_file", fileRequest.downloadHandler.data, "audiofile.wav", "audio/wav"));
UnityWebRequest request = UnityWebRequest.Post(url, form);
request.SetRequestHeader("Accept","application/json");
long sendTime = System.DateTime.Now.Ticks;
yield return request.Send();
Response
{"error":true,"error_code":400,"error_string":"Validation errors.","errors":["The auth token field is required.","The device id field is required."]}
Request contents POST /v1/recording HTTP/1.1 Host: —Redacted— User-Agent: UnityPlayer/5.4.0f3 (UnityWebRequest/1.0, libcurl/7.46.0-DEV) Accept-Encoding: deflate, gzip Accept: application/json X-Unity-Version: 5.4.0f3 Content-Length: 119649 Content-Type: application/x-www-form-urlencoded Expect: 100-continue
GXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="device_id"
Content-Type: text/plain; encoding=utf-8
a65a9cfa-0512-49f3-9277-88f7cb569225GXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="version"
Content-Type: text/plain; encoding=utf-8
FXO3jWqroShnTAZ9O76SCOsCWH7YymhDZzDZUquOVkb6PeSlB4bjbQBy3H7O8R6m/0.2GXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="auth_token"
Content-Type: text/plain; encoding=utf-8
9FxYOIeI15LQStQ6GXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="subject"
Content-Type: text/plain; encoding=utf-8
PluginTestGXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="username"
Content-Type: text/plain; encoding=utf-8
TestUserGXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="user_lat"
Content-Type: text/plain; encoding=utf-8
53.3GXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="user_lng"
Content-Type: text/plain; encoding=utf-8
-6.2GXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: form-data; name="country"
Content-Type: text/plain; encoding=utf-8
IEGXKBCF0Z5V0MWdGLu4hVjddJoU8veT2TVIBdiITY
Content-Disposition: file; name="audio_file"; filename="audiofile.wav"
Content-Type: audio/wav
*Here be binary*
Answer by bdovaz · Aug 27, 2016 at 11:24 AM
I have reported it:
https://fogbugz.unity3d.com/default.asp?826626_htlchp13nh8th2to
Answer by IBouzon · Jun 26, 2017 at 06:29 AM
Also, I have experienced that UnityWebRequest does not build up the boundaries properly. The mandatory "--" are missing in the received request.
Your answer

Follow this Question
Related Questions
Unity-Arduino wifi Communication 0 Answers
UnityWebRequest Responds with 405 1 Answer
WWW class doesn't work well. 1 Answer
Unity transform.forward issue 1 Answer
Reading XML working in my computer but not in my Android phone 1 Answer