c++HTTP方式传输文件流备忘

转载自哪里忘记了,但是肯定是csdk一个问题中的回帖。暂时备忘

time_t tNow = time(0);
 char strBoundary[256] = {0};
 tm tmNow = *localtime(&tNow);
 long lTimeTick = GetTickCount();

//boundary字段,区分文件正文和结尾的特殊标志。每当用刀这个字段的时候,前面必须加--
 _snprintf(strBoundary,256,"%s%d%d%d%d%d%d%d",BOUNDARY_FILE_OCX,
   tmNow.tm_year+1900,tmNow.tm_mon+1,tmNow.tm_mday,tmNow.tm_hour,tmNow.tm_min,tmNow.tm_sec,lTimeTick);
#if IS_USE_WININET
        BOOL bRet = FALSE;
        CString strServer, strObject, strHeader, strRet;
        unsigned short nPort;
        DWORD dwServiceType;
  
  char sLocalFileName[256] = {0};
  _snprintf(sLocalFileName,256,"%s",sLocalFilePath);
  int nFilePathLen = strlen(sLocalFilePath);
  int nFileIndex = 0;
  while (nFilePathLen)
  {
   char s = sLocalFilePath[nFilePathLen];
   if (s == '/' || s == '\\')
   {
    break;
   }
   nFilePathLen--;
  }
  

  CString strName;
  strName.Format("%s",sLocalFilePath);
  strName = strName.Right(strName.GetLength() - nFilePathLen - 1);

  //文件开始头,携带一些http文件服务器所需要的一些数据,格式不定。
  char cont_desc[1024];
  sprintf(cont_desc, "--%s\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\n%s\r\n"
   "--%s\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n%s\r\n"
   "--%s\r\nContent-Disposition: form-data; name=\"userName\"\r\n\r\n%s\r\n"
   "--%s\r\nContent-Disposition: form-data; name=\"file\";filename=\"%s\"\r\n"
   "Content-Type: application/octet-stream\r\n\r\n",
   strBoundary,strName.GetBuffer(0),
   strBoundary,strName.GetBuffer(0),
   strBoundary,sUserName,
  strBoundary,strName.GetBuffer(0));

  char boundary_end[1024] = {0};   
  sprintf(boundary_end, "\r\n--%s--\r\n",
  strBoundary);
  
  int fd;
  int file_size = 0;
  int data_size = 0;
  int res;
  char *file_buf = NULL;
  struct stat statBuf;
  // get the size of file
  if(stat(sLocalFilePath, &statBuf) < 0)
  {
   fprintf(stderr, "stat error!\n");
   return NULL;
  }
  file_size = statBuf.st_size;
  
  file_buf = (char*)malloc(file_size);
  if(file_buf == NULL)
  {
   fprintf(stderr, "malloc error!\n");
   return NULL;
  }
  //open & read to the buffer
  fd = open(sLocalFilePath, O_RDONLY, 0);
  if(fd < 0)
  {
   fprintf(stderr, "open error!\n");
   if (file_buf)
   {
    delete file_buf;
    file_buf = NULL;
   }

   return NULL;
  }
  
  res = read(fd, file_buf, file_size);
  if(res < 0)
  {
   fprintf(stderr, "read error!\n");
   
   if (file_buf)
   {
    delete file_buf;
    file_buf = NULL;
   }

   close(fd);
   return NULL;
  }
   //检测输入网址是否正确,病提取ip,端口,和传输地址。

        if(!AfxParseURL(sHttpServer, dwServiceType, strServer, strObject, nPort))
        {
   if (file_buf)
   {
    delete file_buf;
    file_buf = NULL;
   }
   close(fd);
            return sReturn;
        }
        CInternetSession sess;//Create session
 
        CHttpFile* pFile;
        //
        CHttpConnection *pServer = sess.GetHttpConnection(strServer, nPort); 
        if(pServer == NULL)
        {
   if (file_buf)
   {
    delete file_buf;
    file_buf = NULL;
   }
   close(fd);
            return sReturn;
        }

//上传地址sObgect,根据服务器需要可能需要
  char sObgect[256] = {0};
  _snprintf(sObgect,256,"%s%s",strObject,strObject);

        pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,sObgect,NULL,1,NULL,NULL,INTERNET_FLAG_EXISTING_CONNECT); 
        if(pFile == NULL)
        {
   if (file_buf)
   {
    delete file_buf;
    file_buf = NULL;
   }
   close(fd);
            return sReturn;
        }
  char strTmp[256] = {0};

//文件流传输必须使用此种方式

  _snprintf(strTmp,256,"Content-Type: multipart/form-data;charset=utf-8; boundary=%s\r\n",strBoundary);
        bRet = pFile -> AddRequestHeaders(strTmp); 
        bRet = pFile -> AddRequestHeaders("Accept: */*");
  _snprintf(strTmp,256,"Host:%s:%d",strServer,nPort);
  bRet = pFile->AddRequestHeaders(strTmp);
  bRet = pFile->AddRequestHeaders("Connection: Keep-Alive\r\n");
  bRet = pFile->AddRequestHeaders("Cache-Control: no-cache\r\n\r\n");


  //发送数据
  int nAllLen = strlen(cont_desc)+file_size+strlen(boundary_end);
  char *sAllBuf = new char[nAllLen+1];
  memset(sAllBuf,0,nAllLen+1);
  int nOffSet = 0;
  //拷贝数据头
  memcpy(sAllBuf+nOffSet,cont_desc,strlen(cont_desc));
  nOffSet = strlen(cont_desc);
  //拷贝文件数据
  memcpy(sAllBuf+nOffSet,file_buf,file_size);
  nOffSet = strlen(cont_desc)+file_size;
  //拷贝文件结束符
  memcpy(sAllBuf+nOffSet,boundary_end,strlen(boundary_end));
  //一次性将 数据头,文件数据和文件结束符发送过去。

//防止出现单独发送的时候服务器卡掉或者这边卡掉导致数据发送不完全的现象。
  bRet = pFile->SendRequest(NULL,0,sAllBuf,nAllLen);
 //读取服务器返回数据。
        CString strSentence;
        DWORD dwStatus;
        DWORD dwBuffLen = sizeof(dwStatus);
        BOOL bSuccess = pFile->QueryInfo(
            HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,
            &dwStatus, &dwBuffLen);
 
        if( bSuccess && dwStatus>=  200 && dwStatus<300) 
        {
            char buffer[2049];
            memset(buffer, 0, 2049);
            int nReadCount = 0;
            while((nReadCount = pFile->Read(buffer, 2048)) > 0)
            {
                strSentence += buffer;
                memset(buffer, 0, 2049);
            }
            bRet = true;
        }
        else
        {
            bRet = false;
        }
  
  if (file_buf)
  {
   delete file_buf;
   file_buf = NULL;
  }
  if (sAllBuf)
  {
   delete sAllBuf;
   sAllBuf = NULL;
  }
  close(fd);
       
        pFile->Close();
        sess.Close();
  sReturn = new char[strSentence.GetLength()+1];
  _snprintf(sReturn,strSentence.GetLength(),"%s",strSentence.GetBuffer(0));
        return sReturn;

 

你可能感兴趣的:(c++http协议文件流)