通过HTTP协议下载文件的c++代码,可编译运行

3 篇文章 0 订阅
2 篇文章 0 订阅
先在本机建一个网站,启用,然后就可以测试了。
遇到问题:
http请求头中要选择非可持续连接,如果不写这一行while中recv()会一直持续等待输入。(个人理解,没查资料,不知道对不对)

//HTTPClient.h文件

#ifndef HTTPClient_H_
#define HTTPClient_H_


#include <string>
#include <winsock.h>
#include <iostream>
#include <fstream>


#pragma comment(lib,"ws2_32.lib")


//#define tempDirectory "c:\\"
using namespace std;


class HTTPClient
{
public:
    HTTPClient(void);
    ~HTTPClient(void);


   bool HTTPClient::DownloadFile(SOCKET parmSock,string serverName, string sourcePath, string fileName, string localDirectory,string port);


};




#endif


//HTTPClient.cpp文件

#include "HTTPClient.h"


HTTPClient::HTTPClient(void)
{
}


HTTPClient::~HTTPClient(void)
{
}
//for example serverName = "127.0.0.1" or "localhost"
//            sourcePath = "/abc/"
//            fileName = "config.xml"
//              localDirectory = "c:\\"


bool HTTPClient::DownloadFile(SOCKET parmSock,string serverName, string sourcePath, string fileName, string localDirectory,string port)
{
    ofstream fout;
    string newfile = localDirectory + fileName;


	//识别中文路径和文件名
	std::locale::global(std::locale(""));


    fout.open(newfile.c_str(),ios_base::binary);
	if(!fout.is_open())
	{
        cout<<"open newfile error!"<<endl;
	}


    char szBuffer[1024];


	//将目录和文件名中的' '转换为"%20"
	//sourcePath
	int npos = sourcePath.find(" ");
	while(npos + 1)
	{
		npos = sourcePath.find(" ");
		if(npos == -1)
			break;
		sourcePath.replace(npos,strlen(" "),"%20");


	}
	//fileName
	npos = fileName.find(" ");
	while(npos + 1)
	{
		npos = fileName.find(" ");
		if(npos == -1)
			break;
		fileName.replace(npos,strlen(" "),"%20");
	}


    string requestFile = sourcePath + fileName;
	///
	//格式化http头
	//第一行
	sprintf(szBuffer,"GET %s HTTP/1.1\r\n",requestFile.c_str());
	
	//第二行
    strcat(szBuffer,"Host:");
	strcat(szBuffer,serverName.c_str());
	strcat(szBuffer,":");
	strcat(szBuffer,port.c_str());
    strcat(szBuffer,"\r\n");
	
	//第三行
    //strcat(szBuffer,"Accept:*/*");
    /*strcat(szBuffer,"\r\n");


	//
	//第四行(可有可无)
	strcat(szBuffer,"User-Agent:GeneralDownloadApplication");
    strcat(szBuffer,"\r\n");
	*/
	//第五行 非持久连接
	strcat(szBuffer,"Connection:close");
    strcat(szBuffer,"\r\n");
	//最后一行
	strcat(szBuffer,"\r\n");


	int nRet = send(parmSock, szBuffer, strlen(szBuffer), 0);
    if (nRet == SOCKET_ERROR)
    {
        cout<<"send() error"<<endl;
        closesocket(parmSock);    
        return false;
    }


    //
    // Receive the file contents and print to stdout
    //
	///
    	//取出http头,大小应该不超过1024个字节,只在第一次接收时进行处理
	///
	nRet = recv(parmSock, szBuffer, sizeof(szBuffer), 0);
	if (nRet == SOCKET_ERROR)
    {
        cout<<"recv() error"<<endl;
		closesocket(parmSock);
		fout.close();


		WSACleanup();
		return false;
    }
// 
        //判断该文件是否存在 
        std::string strBuffer = szBuffer; 
        std::string firstString = strBuffer.substr(0,strBuffer.find("\r\n")); 
        int File_Exist = firstString.find("200"); 
        if(File_Exist == -1) 
        {  
              cout<<"File not found in the web."<<endl;  
              return false; 
         }	
       //获取文件内容开始位置
	int i = 0;
	while(1)
	{
		if((szBuffer[i]=='\r')&&(szBuffer[i+1]=='\n')&&(szBuffer[i+2]=='\r')&&(szBuffer[i+3]=='\n'))
		{
			break;
		}
		i++;
	}
	//文件内容开始
	int fileBegin = i+4;


	/
	for(i = fileBegin; i < nRet; i++)
	{
		fout.write(&szBuffer[i],sizeof(szBuffer[i]));
	}
	/*static int count = 0;
	count += nRet - fileBegin;
        */
    while(1)
    {
        // Wait to receive, nRet = NumberOfBytesReceived
        nRet = recv(parmSock, szBuffer, sizeof(szBuffer), 0);


		if (nRet == SOCKET_ERROR)
        {
            cout<<"recv() error"<<endl;
			closesocket(parmSock);
			fout.close();


			WSACleanup();
			return false;
        }


		/
		
        //cout<<"\nrecv() returned "<<nRet<<" bytes"<<endl;
        if (nRet == 0)
            break;
        
		// Write to stdout
		count += nRet;
        fout.write(szBuffer,nRet);
    }


    closesocket(parmSock);    
    fout.close();




    WSACleanup();
    return true;
}


//main.cpp文件

#include "HTTPClient.h"
//#include <iostream>
int main()
{
	HTTPClient m;
	//m.DownloadFile("localhost","/abc/","config.xml","D:\\");


	std::string url = "http://localhost/Water lilies.jpg";
	std::string localDirectory = "D:\\中 国\\";
	std::string port = "5550";
//	cout<<m.ContentLengthInt<<endl;
//  cout<<m.RangeInt<<endl;
	///
	std::string removeProtocol;
	std::string serverName;
	std::string sourcePath;
	std::string fileName;


	int ret;


	ret = url.find("http://");
	if(ret != -1)
	{
		removeProtocol = url.substr(strlen("http://"));
	}
	else
	{
		removeProtocol = url;
	}
	
/*	ret = url.find("https://");
	if(ret != -1)
	{
		removeProtocol = url.substr(strlen("https://"));
	}
	else
	{
		removeProtocol = url;
	}
*/
	ret = removeProtocol.find_first_of('/');
	serverName = removeProtocol.substr(0,ret);
	
	int net = removeProtocol.find_last_of('/');
	sourcePath = removeProtocol.substr(ret,net-ret+1);


	fileName = removeProtocol.substr(net+1);
	//
	WSADATA wsaData;
    int nRet;
    //
    // Initialize WinSock.dll
    //
    nRet = WSAStartup(0x101, &wsaData);
    if (nRet)
    {
        WSACleanup();
        return false;
    }


    if (wsaData.wVersion != 0x101)
    {
        WSACleanup();
        return false;
    }
	
	IN_ADDR        iaHost;
    LPHOSTENT    lpHostEntry;


    iaHost.s_addr = inet_addr(serverName.c_str());
    if (iaHost.s_addr == INADDR_NONE)
    {
        // Wasn't an IP address string, assume it is a name
        lpHostEntry = gethostbyname(serverName.c_str());
    }
    else
    {
        // It was a valid IP address string
        lpHostEntry = gethostbyaddr((const char *)&iaHost, 
                        sizeof(struct in_addr), AF_INET);
    }
    if (lpHostEntry == NULL)
    {
        cout<<"gethostbyname() error"<<endl;
        return false;
    }


    //    
    // Create a TCP/IP stream socket
    //
    SOCKET    parmSock;    


    parmSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (parmSock == INVALID_SOCKET)
    {
        cout<<"socket() error"<<endl; 
        return false;
    }


    //
    // Find the port number for the HTTP service on TCP
    //
    LPSERVENT lpServEnt;
    SOCKADDR_IN saServer;


    lpServEnt = getservbyname("http", "tcp");
    if (lpServEnt == NULL)
        saServer.sin_port = htons(80);
    else
		saServer.sin_port = lpServEnt->s_port;




    //
    // Fill in the rest of the server address structure
    //
    saServer.sin_family = AF_INET;
    saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);




    //
    // Connect the socket
    //
    nRet = connect(parmSock, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN));
    if (nRet == SOCKET_ERROR)
    {
        cout<<"connect() error"<<endl;
        closesocket(parmSock);
        return false;
    }
	//
	m.DownloadFile(parmSock,serverName,sourcePath,fileName,localDirectory,port);




	system("pause");
	return 0;
}
 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值