Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Unitywebrequest using multipart/form-data

Discussion in 'Getting Started' started by orehapunnu, May 13, 2022.

  1. orehapunnu

    orehapunnu

    Joined:
    Jan 28, 2021
    Posts:
    9
    I try to upload content for entry in Cloud Content Delivry System using unitywebrequest, but I fail to upload content and get alert "HTTP/1.1 400 Bad Request". The cause may be that the setting of multipart/form-data of unitywebrequest is wrong.
    (I have already successd "upload content for entry" via curl command and made sure the unitywebrequest code without multipart/form-data part is correct)
    Could you teach which code below is wrong? (Extracted only the code related to multipart / form-data prat)

    Code (CSharp):
    1.        //Upload content for entry
    2.  
    3.             UploadResponseBody responseBodyJson = JsonUtility.FromJson<UploadResponseBody>(entry.downloadHandler.text);
    4.             //get entryid when create entry API response
    5.             string resopnseBodyEntryid = responseBodyJson.entryid;
    6.             //make request body " "file":{} "
    7.             UploadContentRequestBody uploadContentRequestBody = new UploadContentRequestBody();
    8.             string contentRequestBodyJson = Newtonsoft.Json.JsonConvert.SerializeObject(uploadContentRequestBody);
    9.             byte[] contentBody = Encoding.UTF8.GetBytes(contentRequestBodyJson);
    10.  
    11.             //multipart/dorm-data set
    12.             List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
    13.             var bytes = File.ReadAllBytes(datapath);
    14.             string filename = Path.GetFileName(datapath);
    15.             formData.Add(new MultipartFormFileSection(filename, bytes ));
    16.             byte[] boundary = UnityWebRequest.GenerateBoundary();
    17.             byte[] formSections = UnityWebRequest.SerializeFormSections(formData, boundary);
    18.            
    19.             string contentpaths = string.Format("https://content-api.cloud.unity3d.com/api/v1/environments/{0}/buckets/{1}/entries/{2}/content/", _cCDParameterConfig.Environments_ID, _cCDParameterConfig.Brucket_ID, resopnseBodyEntryid);
    20.             UnityWebRequest content = UnityWebRequest.Post(contentpaths, formData, formSections);
    21.             content.method = "PATCH";
    22.  
    23.             content.uploadHandler = new UploadHandlerRaw(contentBody);
    24.             content.uploadHandler.contentType = "multipart/form-data; boundary=" + System.Text.Encoding.UTF8.GetString(boundary, 0, boundary.Length);
    25.             content.downloadHandler = new DownloadHandlerBuffer();
    26.             content.SetRequestHeader("AUTHORIZATION", authorization);
    27.             content.SetRequestHeader("Content-Type", "multipart/form-data");
    28.  
    29.             await content.SendWebRequest();
    30.  
    31.             if (content.isNetworkError || content.isHttpError)
    32.             {
    33.                 Debug.Log(content.error);
    34.             }
    35.             else
    36.             {
    37.                 if (content.responseCode == 200)
    38.                 {
    39.                     Debug.Log("content success");
    40.                     Debug.Log(content.downloadHandler.text);
    41.                 }
    42.                 else
    43.                 {
    44.                     Debug.Log("content failed");
    45.                     Debug.Log(content.responseCode);
    46.                     Debug.Log(content.downloadHandler.text);
    47.                 }
    48.             }
    49.         }
    50.  
    51.  
    52.         string authenticate(string username, string password)
    53.         {
    54.             string auth = username + ":" + password;
    55.             auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
    56.             auth = "Basic " + auth;
    57.             return auth;
    58.         }
    59.  
    60.         [Serializable]
    61.         public class UploadContentRequestBody
    62.         {
    63.             public Dictionary<string, string> file = new Dictionary<string, string>();
    64.         }
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @orehapunnu I would recommend that you use Charles Proxy to compare your working request to the one that is not. We should be able to easily spot the differences. Save both captures in .chls files and post them here for review.
     
  3. orehapunnu

    orehapunnu

    Joined:
    Jan 28, 2021
    Posts:
    9
    @JeffDUnity3D Thank you for replying my question. I send you the difference of http request body in charles proxy between correct result using curl command and my unitywebrequest code which is attatched again. I predict that the error is caused by the blank on the first line in http request body. Could you tell me how I should revise the code?


    Code (CSharp):
    1.  //Upload content for entry
    2.  
    3.             UploadResponseBody responseBodyJson = JsonUtility.FromJson<UploadResponseBody>(entry.downloadHandler.text);
    4.             //get entryid when create entry API response
    5.             string resopnseBodyEntryid = responseBodyJson.entryid;
    6.             UploadContentRequestBody uploadContentRequestBody = new UploadContentRequestBody();
    7.             string contentRequestBodyJson = Newtonsoft.Json.JsonConvert.SerializeObject(uploadContentRequestBody);
    8.             byte[] contentBody = Encoding.UTF8.GetBytes(contentRequestBodyJson);
    9.  
    10.             //multipart/dorm-data set
    11.             List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
    12.             var bytes = File.ReadAllBytes(datapath);
    13.             string filename = Path.GetFileName(datapath);
    14.             formData.Add(new MultipartFormFileSection(filename, bytes));
    15.             byte[] boundary = UnityWebRequest.GenerateBoundary();
    16.             // Debug.Log($"boundary: {System.Text.Encoding.UTF8.GetString(boundary, 0, boundary.Length)}");
    17.             // byte[] formSections = UnityWebRequest.SerializeFormSections(formData, boundary);
    18.  
    19.             string contentpaths = string.Format("https://content-api.cloud.unity3d.com/api/v1/environments/{0}/buckets/{1}/entries/{2}/content/", _cCDParameterConfig.Environments_ID, _cCDParameterConfig.Brucket_ID, resopnseBodyEntryid);
    20.             UnityWebRequest content = UnityWebRequest.Post(contentpaths, formData, boundary);
    21.             content.method = "PATCH";
    22.  
    23.             content.downloadHandler = new DownloadHandlerBuffer();
    24.             content.SetRequestHeader("AUTHORIZATION", authorization);
    25.             content.SetRequestHeader("Content-Type", "multipart/form-data");
    26.  
    27.             await content.SendWebRequest();
    28.  
    29.             if (content.isNetworkError || content.isHttpError)
    30.             {
    31.                 Debug.Log(content.error);
    32.             }
    33.             else
    34.             {
    35.                 if (content.responseCode == 200)
    36.                 {
    37.                     Debug.Log("content success");
    38.                     Debug.Log(content.downloadHandler.text);
    39.                 }
    40.                 else
    41.                 {
    42.                     Debug.Log("content failed");
    43.                     Debug.Log(content.responseCode);
    44.                     Debug.Log(content.downloadHandler.text);
    45.                 }
    46.             }
    47.         }
    48.  
    49.  
    50.         string authenticate(string username, string password)
    51.         {
    52.             string auth = username + ":" + password;
    53.             auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
    54.             auth = "Basic " + auth;
    55.             return auth;
    56.         }
    57.  
    58.         [Serializable]
    59.         public class UploadContentRequestBody
    60.         {
    61.             public Dictionary<string, string> file = new Dictionary<string, string>();
    62.         }
    63.  
     

    Attached Files:

  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @orehapunnu As .chls files please. You may need to change the extension to txt. But there are clear differences even in your screenshot, like content type
     
  5. orehapunnu

    orehapunnu

    Joined:
    Jan 28, 2021
    Posts:
    9
    I couldn't upload .chls file in unity forum and get error "The uploaded file does not have an allowed extension.". I will send .chls file via unity support &services.
     
  6. orehapunnu

    orehapunnu

    Joined:
    Jan 28, 2021
    Posts:
    9
    I resolved the problem and fixed wrong code to below correct code.
    Thank you.

    Code (CSharp):
    1. formData.Add(new MultipartFormFileSection("file", bytes, filename, "application/octet-stream"));