C++实现上传下载文件,支持windows及iOS、Android

使用方法:

SendAndGet("abc.com", 80, "/index.php", "", "");//GET
SendAndGet("abc.com", 80, "/index.php", "user=abc&pass=123qwe", "");//POST
SendAndGet("abc.com", 80, "/download.php", "", "/download/1.jpg");//GET下载
SendAndGet("abc.com", 80, "/index.php", chr(1)."/record/1,mp3", "");//上传文件并获得服务器返回, chr(1)表示等于1的char。直接用sendFile更简单

.h文件

#pragma once

#include "cocos2d.h"


#ifdef WIN32
//#include <windows.h>
//#include <WinSock.h>
#include <direct.h>  
#include <io.h>  
#else
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SOCKET int
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
#include <stdarg.h>  
#include <sys/stat.h>  

#endif

  
#ifdef WIN32  
#define ACCESS _access  
#define MKDIR(a) _mkdir((a))  
#else  
#define ACCESS access  
#define MKDIR(a) mkdir((a),0755)  
#endif 

USING_NS_CC;



class httpDownSimple : public cocos2d::CCObject {
public:
	int type;
	std::string url;
	const char* serverName;
	int nServerPort;
	const char* _url;
	void go(void *obj);
	std::string savePath;


	//By Lein,SendAndGet 实现了上传和下载,GET、POST灵活使用
	static std::string SendAndGet(const char* server_name, int nServerPort, const char* url, char* data, const char* filePath);
	//SendFile 调用的是SendAndGet
	static std::string SendFile(const char* server_name, int nServerPort, const char* url, const char* filePath);
};
#pragma once


.ccp


#include "httpDownSimple.h"
#include <thread>
#include <stdlib.h>  
#include <string.h> 



int strPos(char *strin, char *seprator) {
	char *right = strstr(strin, seprator);
	if (right == NULL)
		return -1;

	return strlen(strin) - strlen(right);
}

int CreatDir(const char *pDir)  
{  
    int i = 0;  
    int iRet;  
    int iLen;  
    char* pszDir;  
  
    if(NULL == pDir)  
    {  
        return 0;  
    }  
      
    pszDir = strdup(pDir);  
    iLen = strlen(pszDir);  
    // 创建中间目录  
    for (i = 0;i < iLen;i ++)  
    {  
        if (pszDir[i] == '\\' || pszDir[i] == '/')  
        {   
            pszDir[i] = '\0';  
			if(strlen(pszDir)<1){
				pszDir[i] = '/';  
				continue;
			}
            //如果不存在,创建  
            iRet = ACCESS(pszDir,0);  
            if (iRet != 0)  
            {  
                iRet = MKDIR(pszDir);  
                if (iRet != 0)  
                {  
                    return -1;  
                }   
            }  
            //支持linux,将所有\换成/  
            pszDir[i] = '/';  
        }   
    }  
    iRet = MKDIR(pszDir);  
    free(pszDir);  
    return iRet;  
}  

std::string getDir(std::string path) {
	int position;
	int pos1 = path.find_last_of('/');
	int pos2 = path.find_last_of("\\");
	if(pos1>pos2)
		position = pos1;
	else position = pos2;
	if(position == -1)
		return path;
	std::string localPath = path.substr(0,position+1);
	return localPath;
}

char * ReadFile(char *pathpic, int &pic_len){
	//将图片读取出来
	FILE *fp = fopen(pathpic, "rb");     //打开文件
	if (!fp){
		CCLog("没有找到文件位置:%s", pathpic);
		return NULL;
	}
	fseek(fp, 0, SEEK_END);  //一直寻找到文件尾部
	pic_len = ftell(fp);  //得到图片的长度
	rewind(fp);  //rewind将文件指针指向开头
	char *pic_buf = new char[pic_len + 1];  //开辟一个空间在堆上
	memset(pic_buf, 0, pic_len + 1);  //清空文件指针
	//读取文件内容
	fread(pic_buf,sizeof(char),pic_len,fp);

	fclose(fp);  
 
	return pic_buf;
}	
std::string httpDownSimple::SendFile(const char* server_name, int nServerPort, const char* url, const char* filePath){
	char data[128];
	sprintf(data,"%c%s",1,filePath);
	return httpDownSimple::SendAndGet(server_name, nServerPort, url, data, "");
}
/**
 * 实现上传,下载,GET
 * server_name 服务器ip、域名
 * nServerPort 端口
 * url
 * data post 的数据,如果为空则采用GET,否则POST。data[0] == 1 则表示data是一个文件路径
 * filePath 保存的地址 如果为空则不保存返回,否则保存
 */
std::string httpDownSimple::SendAndGet(const char* server_name, int nServerPort, const char* url, char* data, const char* filePath){
	CCLog("%s !", server_name);
	printf("=============httpDownSimple================");
#ifdef WIN32
    WSADATA wsaData;
	if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
        WSACleanup();
        return "eWSA";
    }
#endif
    
	struct sockaddr_in srv_addr;
	
    SOCKET cli_sock=socket(PF_INET,SOCK_STREAM,0);
    if (cli_sock==INVALID_SOCKET)
        return "eSOC";
 
 	 srv_addr.sin_family = AF_INET;
	 srv_addr.sin_port= ntohs(nServerPort);
	 
    // connect to server 
#ifdef WIN32   
    LPHOSTENT lphost = gethostbyname(server_name);
    if (lphost != NULL)
        srv_addr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
	if (connect(cli_sock,(LPSOCKADDR)&srv_addr,sizeof(srv_addr))==SOCKET_ERROR){
		CCLog("%s connect failed!", server_name);
        return "eCon";
    }
#else
	struct sockaddr_in addr;
	if (inet_aton(server_name, &addr.sin_addr) != 0) {
		srv_addr.sin_addr = addr.sin_addr;
	} else {
		struct hostent *host;
		char **alias;
		host = gethostbyname(server_name);
		if (host == NULL) {			
			return "eRes";
		}else{
			for (alias = host->h_addr_list; *alias != NULL; alias++) {
				srv_addr.sin_addr = *(struct in_addr *) (*alias);
				break;
			}
		}		
	}

	//srv_addr.sin_addr.s_addr = inet_addr(server_name);  // 接收端IP	

	struct timeval rcvto, sndto;
	int tolen = sizeof(struct timeval);

	rcvto.tv_sec = 5;
	rcvto.tv_usec = 0;

	sndto.tv_sec = 5;
	sndto.tv_usec = 0;
	//发送时限
	setsockopt(cli_sock, SOL_SOCKET, SO_SNDTIMEO, &sndto, tolen);
	//接收时限
	setsockopt(cli_sock, SOL_SOCKET, SO_RCVTIMEO, &rcvto, tolen);


	if (connect(cli_sock, (struct sockaddr *) &srv_addr, sizeof(struct sockaddr)) != 0) {
		CCLog("%s connect failed android!", server_name);
		return "eCon-1";
	}
#endif
 
	int dataLen =(int) strlen(data);
	int isfile = 0;
	if(data[0]==1){
		isfile = 1;
		CCLog("Will read file [%s].", data+1);
		data=ReadFile(data+1, dataLen);//dataLen 会被修改成文件大小
		CCLog("The file size=[%d].", dataLen);
	}

	std::string header("");
    //std::string content("");        //文件
    
    //----------------------post头开始--------------------------------  
    header += dataLen>10?"POST ":"GET ";
    header += url;
    header += " HTTP/1.1\r\n";
    header += "Host: ";
    header += server_name;
    header += "\r\n";
    header += "Connection: Close\r\n";
	
	if(dataLen>10){
        CCLog("dataLen=[%d].", dataLen);
        char tmp[32];
        tmp[0]=0;
        sprintf(tmp,"%d",dataLen);
        std::string str_cl = tmp;
        CCLog("str_cl=[%s].", str_cl.c_str());
		
		//使得$_POST['key']可取得数据,否则只能用$HTTP_RAW_POST_DATA获取数据
		if(!isfile)
			header += "Content-Type: application/x-www-form-urlencoded\r\n";
		header += "Content-Length: ";
		header += str_cl;
		header += "\r\n\r\n";
		//header += data;
	}else header += "\r\n";
	
	
    CCLog("header=[%s].", header.c_str());
	//----------------------post头结束-----------------------------------
	//发送post头  
	int retval = (int) send(cli_sock, header.c_str(), header.length(), 0);
	
	if( SOCKET_ERROR == retval )
        return "";
	
	if(dataLen>10){
		CCLog("Will send %d/%ld body.", dataLen, strlen(data));
		int sendCount = 0;
		while(sendCount<dataLen){
			retval = (int) send(cli_sock, data+sendCount, dataLen-sendCount, 0);
			if( SOCKET_ERROR == retval )
				return "";
			sendCount+=retval;
			CCLog("Sending [%d/%d].", sendCount, dataLen);
		}
	}
	
	//释放内存
	delete data;
	
    int buffsize=10240;
    char buffer[10240]={0};
	int iPos;

	int	header_end=0;
	char hender[] = "\r\n\r\n";  
	char *p;
	std::string result("");

	int len = 0;
	
	FILE *fp = NULL;
	
	if(strlen(filePath)>3){
		fopen(filePath, "wb+");
		if(fp==NULL){
			return "eFp";
		}
	}
    std::string tmps;
    while( SOCKET_ERROR != retval ){
        retval = (int)recv(cli_sock ,buffer,buffsize-1,0);
		if(retval > 0) {
			if(header_end<1){
				iPos = strPos(buffer, hender);  
				if(iPos!=-1)
				{					
					p = buffer+iPos+4;
					len= retval-(iPos+4);
					header_end = 1;
                    buffer[retval]=0;
                    CCLog("found head, data len=%d,iPos=%d,retval=%d",len,iPos+4,retval);
                    CCLog("server header=[%s]", buffer);
				}else CCLog("in head len=%d",retval);
			}else{
                CCLog("body got len=%d",len);
				len = retval;
				p = buffer;
			}

			if(header_end>0){
				if(fp!=NULL) 
					fwrite(p, len, 1, fp);
				else
					result += p;
				std::chrono::milliseconds timespan(5);// or whatever
				std::this_thread::sleep_for(timespan);
			}
            if(retval<buffsize-1) break;
		}else break;
    }
	
#ifdef WIN32   
    closesocket(cli_sock);
#else
	close(cli_sock);
#endif
	
	
	if(fp==NULL)
		return result;
	else{
		fclose(fp);
		return filePath;
	}
}



  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值