title: Implementing CURL command using libcurl in C/C++
body: <p>The <code>CURL</code> command that I am using is shown below.</p>
  
  <pre><code>curl -F 'file=@/home/karthik/Workspace/downloadfile.out' http://127.0.0.1:5000/file-upload --verbose
  </code></pre>
  
  <p>The response from the server is shown below.</p>
  
  <pre><code>*   Trying 127.0.0.1...
  * Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
  &gt; POST /file-upload HTTP/1.1
  &gt; Host: 127.0.0.1:5000
  &gt; User-Agent: curl/7.47.0
  &gt; Accept: */*
  &gt; Content-Length: 663876790
  &gt; Expect: 100-continue
  &gt; Content-Type: multipart/form-data; boundary=------------------------4e96ef0714498bd7
  &gt; 
  &lt; HTTP/1.1 100 Continue
  * HTTP 1.0, assume close after body
  &lt; HTTP/1.0 201 CREATED
  &lt; Content-Type: application/json
  &lt; Content-Length: 46
  &lt; Server: Werkzeug/0.16.0 Python/3.5.2
  &lt; Date: Sat, 14 Dec 2019 07:05:15 GMT
  &lt; 
  {
    "message": "File successfully uploaded"
  }
  * Closing connection 0
  </code></pre>
  
  <p>I want to implement the same command in C/C++ using libcurl. I am using the following function.</p>
  
  <pre><code>int FileUploadDownload::upload(const std::string &amp;filename, const std::string &amp;url) {
  
      CURL *curl;
      CURLcode res;
      struct stat file_info;
      curl_off_t speed_upload, total_time;
      FILE *fd;
  
      fd = fopen(filename.c_str(), "rb");
      if(!fd) {
          m_logger-&gt;errorf("unable to open file: %s\n",strerror(errno));
          return 1;
      }
      if(fstat(fileno(fd), &amp;file_info) != 0) {
          m_logger-&gt;errorf("unable to get file stats: %s\n",strerror(errno));
          return 2;
      }
  
      std::cout &lt;&lt; "filename : "&lt;&lt; filename &lt;&lt; std::endl;
      std::cout &lt;&lt; "url : " &lt;&lt; url &lt;&lt; std::endl;
  
      curl = curl_easy_init();
      if(curl) {
  
          curl_easy_setopt(curl, CURLOPT_URL,
                           url.c_str());
  
          curl_easy_setopt(curl, CURLOPT_POSTFIELDS, filename.c_str());
          curl_easy_setopt(curl, CURLOPT_POST, 1L);
          curl_easy_setopt(curl, CURLOPT_READDATA, fd);
          curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
                           (curl_off_t) file_info.st_size);
          curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  
          res = curl_easy_perform(curl);
          if (res != CURLE_OK) {
              m_logger-&gt;errorf("curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
          } else {
              curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &amp;speed_upload);
              curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &amp;total_time);
              m_logger-&gt;infof("Speed: %" CURL_FORMAT_CURL_OFF_T " bytes/sec during %"
                              CURL_FORMAT_CURL_OFF_T ".%06ld seconds\n",
                              speed_upload,
                              (total_time / 1000000), (long) (total_time % 1000000));
          }
      }
      return 0;
  }
  </code></pre>
  
  <p>The below is the result that I get from the server.</p>
  
  <pre><code>The result that I get is shown below.
     *   Trying 127.0.0.1...
  * Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
  &gt; POST /file-upload HTTP/1.1
  &gt; Host: 127.0.0.1:5000
  &gt; User-Agent: curl/7.47.0
  &gt; Accept: */*
  &gt; Content-Length: 550
  &gt; Expect: 100-continue
  &gt; Content-Type: multipart/form-data; boundary=------------------------c8ef4837136fca99
  &gt; 
  &lt; HTTP/1.1 100 Continue
  * HTTP 1.0, assume close after body
  &lt; HTTP/1.0 201 CREATED
  &lt; Content-Type: application/json
  &lt; Content-Length: 46
  &lt; Server: Werkzeug/0.16.0 Python/3.5.2
  &lt; Date: Sat, 14 Dec 2019 07:09:47 GMT
  &lt; 
  {
    "message": "File successfully uploaded"
  }
  * Closing connection 0
  </code></pre>
  
  <p>My aim is to mimic the curl command above in the C/C++ code below. What am I doing wrong ?</p>
  
  <p>I have some difficulty in update to the latest libcurl. However I tried to set the HTTPHEADERS manually as follows.</p>
  
  <pre><code>    stringstream ss;
  
      ss &lt;&lt; "Content-Type:" &lt;&lt; " multipart/form-data";
      list = curl_slist_append(list, ss.str().c_str());
      ss.str(std::string());
  
      ss &lt;&lt; "filename=" &lt;&lt; filename;
      list = curl_slist_append(list, ss.str().c_str());
      ss.str(std::string());
  
      ss &lt;&lt; "name=file";
      list = curl_slist_append(list, ss.str().c_str());
      ss.str(std::string());
  
      ss &lt;&lt; "Content-Type:" &lt;&lt; " text/plain";
      list = curl_slist_append(list, ss.str().c_str());
      ss.str(std::string());
  
      ss &lt;&lt; "Content-Disposition:" &lt;&lt; " form-data";
      list = curl_slist_append(list, ss.str().c_str());
  
      curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
  </code></pre>
  
  <p>But the below code doesn't seem to work. Is the above approach valid ? If yes, what am I doing wrong?</p>