title: Uploading multipart/form-data on Android using OKHttp
body: <p>I was trying to upload Multipart/form-data on Android using Okhttp, but it does not work.</p>
  <p>The request header is</p>
  <p>POST /api/texttospeech/v3.0-beta1//datasets/upload HTTP/1.1
  Host: koreacentral.customvoice.api.speech.microsoft.com
  Connection: keep-alive
  Content-Length: 201455
  Accept: application/json, text/plain, <em>/</em>
  Correlation-Id: 290c5850-f621-11ea-ac4a-9dac0e19cc7b
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51
  Ocp-Apim-Subscription-Key: 38fae10960fc477ba614c6dfe64613ba
  Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Origin: <a href="https://speech.microsoft.com" rel="nofollow noreferrer">https://speech.microsoft.com</a>
  Sec-Fetch-Site: same-site
  Sec-Fetch-Mode: cors
  Sec-Fetch-Dest: empty
  Accept-Encoding: gzip, deflate, br
  Accept-Language: ko,en;q=0.9,en-US;q=0.8</p>
  <p>and the multipart/form-data is</p>
  <p>------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;projectId&quot;</p>
  <p>1a685f5d-400b-4801-8adb-9d359cad27cb
  ------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;name&quot;</p>
  <p>16151
  ------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;description&quot;</p>
  <p>51561
  ------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;dataImportKind&quot;</p>
  <p>CustomVoice
  ------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;locale&quot;</p>
  <p>en-US
  ------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;properties&quot;</p>
  <p>{&quot;Gender&quot;:&quot;Male&quot;,&quot;IsMixLingual&quot;:&quot;false&quot;,&quot;PortalAPIVersion&quot;:&quot;3&quot;}
  ------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;audiodata&quot;; filename=&quot;1.zip&quot;
  Content-Type: application/x-zip-compressed</p>
  <p>------WebKitFormBoundaryZAaHsREIpzJ9sBHS
  Content-Disposition: form-data; name=&quot;transcriptions&quot;; filename=&quot;transcript.txt&quot;
  Content-Type: text/plain</p>
  <p>------WebKitFormBoundaryZAaHsREIpzJ9sBHS--</p>
  <p>The code I created is something like this.</p>
  <p>String boundary = &quot;----WebKitFormBoundary&quot; + result; //result is the random digits</p>
  <pre><code>        String Url = String.format(&quot;https://%s.customvoice.api.speech.microsoft.com/api/texttospeech/v3.0-beta1//datasets/upload&quot;, region);
          String audioPath = getFilesDir().getAbsolutePath()+&quot;/audios.zip&quot;;
          String scriptPath = getFilesDir().getAbsolutePath()+&quot;/script.txt&quot;;
  
          System.out.println(&quot;properties to String&quot;+ properties.toString());
  
          File audioFile = new File(audioPath);
          File scriptFile = new File(scriptPath);
          //Create request body (params or json)
          System.out.println(&quot;audiopath is &quot; + audioPath);
          System.out.println(&quot;scriptpath is &quot;+ scriptPath);
  
          MultipartBody formBody = new MultipartBody.Builder(boundary)
                  .setType(MultipartBody.FORM)
                  .addFormDataPart(&quot;projectId&quot;, projectId)
                  .addFormDataPart(&quot;name&quot;, defaultVal)
                  .addFormDataPart(&quot;description&quot;, defaultVal)
                  .addFormDataPart(&quot;dataImportKind&quot;, &quot;CustomVoice&quot;)
                  .addFormDataPart(&quot;locale&quot;, &quot;en-US&quot;)
                  .addFormDataPart(&quot;properties&quot;, properties.toString())
                  .addFormDataPart(&quot;audiodata&quot;, &quot;audios.zip&quot;, RequestBody.create(MediaType.parse(&quot;application/x-zip-compressed&quot;), audioFile))
                  .addFormDataPart(&quot;transcriptions&quot;, &quot;script.txt&quot;, RequestBody.create(MediaType.parse(&quot;text/plain&quot;), scriptFile))
                  .build();
  
  
          System.out.println(formBody);
  
  
          Request request = new Request.Builder()
  
                  .header(&quot;Ocp-Apim-Subscription-Key&quot;, subKey)
                  .addHeader(&quot;Ocp-Apim-Subscription-Key&quot;, subKey)
                  .addHeader(&quot;Content-Type&quot;, formBody.contentType().toString())
                  .post(formBody)
                  .url(Url)
                  .build();
  
          System.out.println(&quot;Data upload request : &quot;+ request);
          System.out.println(&quot;Data upload request : &quot;+ request.body());
          System.out.println(&quot;Data upload request : &quot;+ request.body().toString());
          //Response response = client.newCall(request).execute();
          //System.out.println(&quot;data upload response &quot;+response.body().string());
          //response.close();
          Call call = client.newCall(request);
          call.enqueue(new Callback() {
              @Override
              public void onFailure(@NotNull Call call, @NotNull IOException e) {
                  e.printStackTrace();
              }
  
              @Override
              public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                  System.out.println(&quot;Response &quot;+response);
              }
          });
          return null;
      }
  </code></pre>
  <p>The error is</p>
  <p>Response{protocol=http/1.1, code=500, message=Internal Server Error, url=https://koreacentral.customvoice.api.speech.microsoft.com/api/texttospeech/v3.0-beta1//datasets/upload}</p>
  <p>The Internal Server Error seems to be wrong, since it works if I send the request through Python, using</p>
  <p>from requests_toolbelt.multipart.encoder import MultipartEncoder</p>