libcurl应用:上传文件到服务器

1、Http协议put方式

#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>

/*
 * This example shows a HTTP PUT operation. PUTs a file given as a command
 * line argument to the URL also given on the command line.
 *
 * This example also uses its own read callback.
 *
 * Here's an article on how to setup a PUT handler for Apache:
 * http://www.apacheweek.com/features/put
 */

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t retcode;
  curl_off_t nread;

  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */
  retcode = fread(ptr, size, nmemb, stream);

  nread = (curl_off_t)retcode;

  fprintf(stderr, "*** We read %" CURL_FORMAT_CURL_OFF_T
          " bytes from file\n", nread);

  return retcode;
}

int main(int argc, char **argv)
{
  CURL *curl;
  CURLcode res;
  FILE * hd_src ;
  struct stat file_info;

  char *file;
  char *url;

  if(argc < 3)
    return 1;

  file= argv[1];
  url = argv[2];

  /* get the file size of the local file */
  stat(file, &file_info);

  /* get a FILE * of the same file, could also be made with
     fdopen() from the previous descriptor, but hey this is just
     an example! */
  hd_src = fopen(file, "rb");

  /* In windows, this will init the winsock stuff */
  curl_global_init(CURL_GLOBAL_ALL);

  /* get a curl handle */
  curl = curl_easy_init();
  if(curl) {
    /* we want to use our own read function */
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

    /* enable uploading */
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

    /* HTTP PUT please */
    curl_easy_setopt(curl, CURLOPT_PUT, 1L);

    /* specify target URL, and note that this URL should include a file
       name, not only a directory */
    curl_easy_setopt(curl, CURLOPT_URL, url);

    /* now specify which file to upload */
    curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);

    /* provide the size of the upload, we specicially typecast the value
       to curl_off_t since we must be sure to use the correct data size */
    curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
                     (curl_off_t)file_info.st_size);

    /* Now run off and do what you've been told! */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  fclose(hd_src); /* close the local file */

  curl_global_cleanup();
  return 0;
}

2、提交表单方式



#include <stdio.h>
#include <string.h>
#include <sys/time.h>

#include <curl/curl.h>

int main(void)
{
  CURL *curl;

  CURLM *multi_handle;
  int still_running;

  struct curl_httppost *formpost=NULL;
  struct curl_httppost *lastptr=NULL;
  struct curl_slist *headerlist=NULL;
  static const char buf[] = "Expect:";

  /* Fill in the file upload field. This makes libcurl load data from
     the given file name when curl_easy_perform() is called. */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "sendfile",
               CURLFORM_FILE, "postit2.c",
               CURLFORM_END);

  /* Fill in the filename field */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "filename",
               CURLFORM_COPYCONTENTS, "postit2.c",
               CURLFORM_END);

  /* Fill in the submit field too, even if this is rarely needed */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "submit",
               CURLFORM_COPYCONTENTS, "send",
               CURLFORM_END);

  curl = curl_easy_init();
  multi_handle = curl_multi_init();

  /* initialize custom header list (stating that Expect: 100-continue is not
     wanted */
  headerlist = curl_slist_append(headerlist, buf);
  if(curl && multi_handle) {

    /* what URL that receives this POST */
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/upload.cgi");
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

    curl_multi_add_handle(multi_handle, curl);

    curl_multi_perform(multi_handle, &still_running);

    do {
      struct timeval timeout;
      int rc; /* select() return code */
      CURLMcode mc; /* curl_multi_fdset() return code */

      fd_set fdread;
      fd_set fdwrite;
      fd_set fdexcep;
      int maxfd = -1;

      long curl_timeo = -1;

      FD_ZERO(&fdread);
      FD_ZERO(&fdwrite);
      FD_ZERO(&fdexcep);

      /* set a suitable timeout to play around with */
      timeout.tv_sec = 1;
      timeout.tv_usec = 0;

      curl_multi_timeout(multi_handle, &curl_timeo);
      if(curl_timeo >= 0) {
        timeout.tv_sec = curl_timeo / 1000;
        if(timeout.tv_sec > 1)
          timeout.tv_sec = 1;
        else
          timeout.tv_usec = (curl_timeo % 1000) * 1000;
      }

      /* get file descriptors from the transfers */
      mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

      if(mc != CURLM_OK)
      {
        fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
        break;
      }

      /* On success the value of maxfd is guaranteed to be >= -1. We call
         select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
         no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
         to sleep 100ms, which is the minimum suggested value in the
         curl_multi_fdset() doc. */

      if(maxfd == -1) {
#ifdef _WIN32
        Sleep(100);
        rc = 0;
#else
        /* Portable sleep for platforms other than Windows. */
        struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
        rc = select(0, NULL, NULL, NULL, &wait);
#endif
      }
      else {
        /* Note that on some platforms 'timeout' may be modified by select().
           If you need access to the original value save a copy beforehand. */
        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
      }

      switch(rc) {
      case -1:
        /* select error */
        break;
      case 0:
      default:
        /* timeout or readable/writable sockets */
        printf("perform!\n");
        curl_multi_perform(multi_handle, &still_running);
        printf("running: %d!\n", still_running);
        break;
      }
    } while(still_running);

    curl_multi_cleanup(multi_handle);

    /* always cleanup */
    curl_easy_cleanup(curl);

    /* then cleanup the formpost chain */
    curl_formfree(formpost);

    /* free slist */
    curl_slist_free_all (headerlist);
  }
  return 0;
}

3、FTP方式

/*****************************************************************************
 函 数 名  : ftp_send
 功能描述  : ftp发送文件
 输入参数  : char *user     ftp服务器用户名            
             char *passwd  ftp服务器密码            
             char*dir      发送文件所在目录,注意目录后有"/",如 "/tmp/path/"            
             char *file     待发送文件名           
 输出参数  : 无
 返 回 值  : 成功,0;失败 -1
*****************************************************************************/
int ftp_send(char *user, char *passwd,  char*dir, char *file)
{
    CURLcode result;
    long ulFileSize;
    FILE*fp = NULL;
    char acUserPwd[128] = "";
    char acFtpForm[256] = "";
    struct in_addr stIp; 
    char acIp[32];
    UINT16 usPort;
    char fileName[256] = "";
 
    /* 获取服务器IP&PORT */
    stIp.s_addr = 0xc0a801f9;       /* 缺省服务器IP地址 192.168.1.249 */ 
    if(inet_ntop(AF_INET, (void *)&stIp, acIp, (socklen_t )sizeof(acIp)) == 0) {
        return -1;
    }
    
    usPort = 2121; 
    
    /* 读取文件 */
    snprintf(fileName, sizeof(fileName),"%s%s", dir, file);
    fp = fopen(fileName, "r");
    if(NULL == fp)
    { 
        return -1;
    }
    fseek(fp, 0L, SEEK_END);
    ulFileSize = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
 
    /* 初始化CURL指针 */
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        fclose(fp);
        return -1;
    }  
    
    snprintf(acUserPwd, 128, "%s:%s", user, passwd);
    snprintf(acFtpForm, 128, "ftp://%s:%u/%s", acIp, usPort, file);
 
    curl_easy_setopt(curl, CURLOPT_USERPWD, acUserPwd);
    curl_easy_setopt(curl, CURLOPT_URL, acFtpForm);
    curl_easy_setopt(curl, CURLOPT_READDATA, fp);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
    curl_easy_setopt(curl, CURLOPT_INFILESIZE, ulFileSize);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
       
    result = curl_easy_perform(curl);
    if(CURLE_OK!=result)
    {   
        curl_easy_cleanup(curl);
        fclose(fp);
        return -1;
    } 
    curl_easy_cleanup(curl);  
    fclose(fp);
 
    return 0; 
}

4、POS二进制码流

int PostStream(struct dsdAAA *dsdAAAObject, char *imagePath,
                  dsdAAACallBack callback, char *userBuf)
{
    char url[512] = { 0 };
    char userp[1024];
    int res = AAA_SUCCESS;
    char *postContent = NULL;
    CURL *curl;
    struct curl_slist *slist = NULL;
    FILE * file;
    struct stat fileInfo;

    if (imagePath == NULL || (dsdAAAObject == NULL)
        || (callback == NULL) || (userBuf == NULL)) {
        dsdl_err("argument can't be empty\n");
        return -AAA_ERROR;
    }

    file = fopen(imagePath, "rb");
    if (file == NULL) {
        dsdl_err("open file failed\n");
        return -AAA_ERROR;
    }
    stat(imagePath, &fileInfo);// get file size
    long fileSize = fileInfo.st_size;
    dsdl_debug("文件大小是 = %ld\n", fileSize);
    postContent = (char*)malloc(fileSize);
    if (postContent == NULL) {
        dsdl_err("malloc failed\n");
        return -AAA_ERROR;
    }
    int readCount = fread(postContent, 1, fileSize, file);
    if (readCount != fileSize) {
        dsdl_err("read file failed\n");
        fclose(file);
        free(postContent);
        return -AAA_ERROR;
    }


    snprintf(url, sizeof(url), "%s/update_portrait?token=%s",
             dsdAAAObject->serverUrl, dsdAAAObject->token);
    dsdl_debug("url = %s\n", url);

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.38.0");
        slist = curl_slist_append(slist, "Content-Type: image/png");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, userp);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlCallback);
        dsdl_debug("dsdAAAObject->cookie = %s\n", dsdAAAObject->cookie);
        curl_easy_setopt(curl, CURLOPT_COOKIELIST, dsdAAAObject->cookie);// 设置cookie
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_READDATA, file);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, fileSize);//指定图片大小,否则遇到'\0'就停止了
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postContent);

        dsdl_debug("start send file to server\n");
        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            dsdl_err("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
            res = -AAA_ERROR;
            goto END;
        }
        curl_easy_cleanup(curl);

        callback(userp, userBuf);
    }

END:
    fclose(file);
    free(postContent);
    curl_global_cleanup();
    return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

previewer1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值