title: C++ cUrl Send mulipart/form-data file to webserver
body: <p>like the title says I want to send a file with the cUrl lib in a C++ program to a webserver.</p>
  
  <p>I got the url from the server and information that it wants the HTTP POST methode and in mutipart/ form-data. Also it wants a parameter file with the data.</p>
  
  <p>I also got a cUrl-call which works with the curl console:</p>
  
  <blockquote>
    <p>curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data " -F "file=@test.txt" "url"</p>
  </blockquote>
  
  <p>If I run the code below, the server bring the answer that there is no upload or no multipart form.</p>
  
  <p>And now my code:</p>
  
  <pre><code>//## File stuff
  struct stat file_info;
  FILE *fd;
  
  fopen_s(&amp;fd,"file.txt", "rb"); /* open file to upload */
  if (!fd) {
  
      return 1; /* can't continue */
  }
  
  /* to get the file size */
  if (fstat(_fileno(fd), &amp;file_info) != 0) {
  
      return 1; /* can't continue */
  }
  //##
  
  CURL *hnd = curl_easy_init();
  
  curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
  curl_easy_setopt(hnd, CURLOPT_URL, "url");
  
  struct curl_slist *headers = NULL;
  headers = curl_slist_append(headers, "cache-control: no-cache");
  headers = curl_slist_append(headers, "content-type: multipart / form-data");
  curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
  
  curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
  curl_easy_setopt(hnd, CURLOPT_READDATA, fd);
  
  curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE,(curl_off_t)file_info.st_size);
  
  CURLcode ret = curl_easy_perform(hnd);
  </code></pre>
  
  <h2>Edit</h2>
  
  <p>New code with file from buffer:</p>
  
  <pre><code>std::string contents;
  std::ifstream in("empty.txt", std::ios::in | std::ios::binary);
  
  if (in)
  {
      in.seekg(0, std::ios::end);
      contents.resize(in.tellg());
      in.seekg(0, std::ios::beg);
      in.read(&amp;contents[0], contents.size());
      in.close();
  }
  
  CURL *hnd = curl_easy_init();
  
  uint32_t size = contents.size();
  
  //struct curl_slist *headers = NULL;
  //headers = curl_slist_append(headers, "cache-control: no-cache");
  //headers = curl_slist_append(headers, "content-type: multipart/form-data");
  //curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
  
  curl_easy_setopt(hnd, CURLOPT_URL, "url");
  curl_easy_setopt(hnd, CURLOPT_POST, 1);
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, contents.data());
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE, size);
  
  CURLcode ret = curl_easy_perform(hnd);
  </code></pre>
  
  <p>Now the server response that there is no file data. Have I also to say that it is multipart/form-data? But if i uncomment the header setting the response is an Error about the multiform boundary.
  I´m also confused about the "file" parameter which is wanted. Do i have to add it to the CURLOPT_POSTFIELDS?</p>
  
  <p>Hope one of you can help me thanks!</p>
  
  <h1>Edit Final</h1>
  
  <p>I got it. The following code works for me with the give server settings.</p>
  
  <pre><code>std::string contents;
  std::ifstream in("file.txt", std::ios::in | std::ios::binary);
  
  if (in)
  {
      in.seekg(0, std::ios::end);
      contents.resize(in.tellg());
      in.seekg(0, std::ios::beg);
      in.read(&amp;contents[0], contents.size());
      in.close();
  }
  //##
  
  
  CURL *curl;
  CURLcode res;
  
  struct curl_httppost *formpost = NULL;
  struct curl_httppost *lastptr = NULL;
  struct curl_slist *headerlist = NULL;
  static const char buf[] =  "Expect:";
  
  curl_global_init(CURL_GLOBAL_ALL);
  
  // set up the header
  curl_formadd(&amp;formpost,
      &amp;lastptr,
      CURLFORM_COPYNAME, "cache-control:",
      CURLFORM_COPYCONTENTS, "no-cache",
      CURLFORM_END);
  
  curl_formadd(&amp;formpost,
      &amp;lastptr,
      CURLFORM_COPYNAME, "content-type:",
      CURLFORM_COPYCONTENTS, "multipart/form-data",
      CURLFORM_END);
  
  curl_formadd(&amp;formpost, &amp;lastptr,
      CURLFORM_COPYNAME, "file",  // &lt;--- the (in this case) wanted file-Tag!
      CURLFORM_BUFFER, "data",
      CURLFORM_BUFFERPTR, contents.data(),
      CURLFORM_BUFFERLENGTH, contents.size(),
      CURLFORM_END);
  
  curl = curl_easy_init();
  
  headerlist = curl_slist_append(headerlist, buf);
  if (curl) {
  
      curl_easy_setopt(curl, CURLOPT_URL, "url");
  
      curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
      //curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
      //curl_easy_setopt(curl, CURLOPT_WRITEDATA, &amp;readBuffer);
      //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  
      res = curl_easy_perform(curl);
      /* Check for errors */
      if (res != CURLE_OK)
          fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
  
  
      curl_easy_cleanup(curl);
  
  
      curl_formfree(formpost);
  
      curl_slist_free_all(headerlist);
  }
  </code></pre>