http下载

来源:互联网 发布:mac repo 下载失败 编辑:程序博客网 时间:2024/06/04 17:41
int httpdownload(const char* url, const char* localfile){const char* pSplitStr = NULL;const char* pTemp = NULL;const char* pLastPos = NULL;const char* pEndPos = NULL;int iTempRet = 0;const int iTempBufSize = 1024;const int iUrlBufSize = 2084;const int iRecvBufSize = 64*1024;const int iHttpHeaderBufSize = 16*1024;bool bUseBreakMode = false;// 是否启用断点续传char* pHost = NULL;char* pRefer = NULL;int iHostPort = 80;char* pFileUrl = NULL;ULONG ulNetIp = 0;struct hostent* lpHostent = NULL;SOCKET scSocket = INVALID_SOCKET;sockaddr_in siSockaddr;char* pHttpRequest = NULL;char* pHttpResponse = NULL;LPBYTE lpBufTemp = (LPBYTE)NULL;DWORD dwDataLen = 0;char* pTempBuf = NULL;char* pHeaderEndPos = NULL;DWORD dwSentTotal = 0;bool bRet = true;int iRecv = 0;int iRecvedTotal = 0;int iRetCode = 0;long lFileOffset = 0;int iTotalDataSize = 0;int iRecvedFileBytes = 0;FILE* fpTempFile = NULL;FILE* fpBreakFile = NULL;char* pBreakFileUrl = NULL;char* pTempFileUrl = NULL;int i = 0;WSADATA wdData;// if ((strlen(url) == 0) || (strlen(url) > 2083) || (url == NULL)){return 1;// 无效的参数}if ((strlen(localfile) == 0) || (localfile == NULL)){return 1;// 无效的参数}// iTempRet = WSAStartup(0x0202, &wdData);if (iTempRet != 0){return 2;}// pHost = (char*)malloc(iUrlBufSize);pRefer = (char*)malloc(iUrlBufSize);pFileUrl = (char*)malloc(iUrlBufSize);pHttpRequest = (char*)malloc(iHttpHeaderBufSize);pHttpResponse = (char*)malloc(iRecvBufSize);pTempBuf = (char*)malloc(iTempBufSize);pBreakFileUrl = (char*)malloc(iTempBufSize);pTempFileUrl = (char*)malloc(iTempBufSize);// __try{if (pHost == NULL || pRefer == NULL || pFileUrl == NULL || pHttpRequest == NULL || pHttpResponse == NULL || pTempBuf == NULL || pBreakFileUrl == NULL || pTempFileUrl == NULL){return 3;}memset(pHost, 0, iUrlBufSize);memset(pRefer, 0, iUrlBufSize);memset(pFileUrl, 0, iUrlBufSize);memset(pHttpRequest, 0, iHttpHeaderBufSize);memset(pHttpResponse, 0, iRecvBufSize);memset(pTempBuf, 0, iTempBufSize);memset(pBreakFileUrl, 0, iTempBufSize);tagDown:// 分割URL,http://www.aaa.com/aaa/aaa或者http://www.aaa.com/aaa/aaa?testpSplitStr = "http://";iTempRet = strnicmp(url, pSplitStr, strlen(pSplitStr));if (iTempRet != 0){return 4;// 无效的地址}// 得到主机名pTemp = url + strlen(pSplitStr);// 查找主机结束符pLastPos = strchr(pTemp, '/');if (pLastPos == NULL){strcpy(pHost, pTemp);pFileUrl[0] = '/';}else{strncpy(pHost, pTemp, pLastPos-pTemp);strcpy(pFileUrl, pLastPos);}// 查找端口pLastPos = strchr(pHost, ':');if (pLastPos == NULL){iHostPort = 80;}else{iHostPort = atoi(pLastPos+1);//*pLastPos = '\0';}// 解析主机lpHostent = gethostbyname(pHost);if (lpHostent == NULL){return 4;}if (lpHostent->h_length < 1){return 4;}// ulNetIp = *(ULONG*)(lpHostent->h_addr_list[0]);// 连接主机scSocket = socket(AF_INET, SOCK_STREAM, 0);if (scSocket == INVALID_SOCKET){return 5;}siSockaddr.sin_family = AF_INET;siSockaddr.sin_addr.S_un.S_addr = ulNetIp;siSockaddr.sin_port = htons(iHostPort);// for (i=0; ;){iTempRet = connect(scSocket, (const struct sockaddr*)&siSockaddr, sizeof(siSockaddr));if (iTempRet != 0){if (++i < 10){Sleep(1000);continue;}return 6;}break;}// 构建HTTP头#define FORMAT_HTTP_GET_REQUEST "GET %s HTTP/1.1\r\n"\"Accept: */*\r\n"\"Accept-Language: zh-CN\r\n"\"User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2)\r\n"\"Host: %s\r\n"\"Cache-Control: no-cache\r\n"\"Expires: 0\r\n"\"Connection: Keep-Alive\r\n"\"Referer: %s\r\n"\"Range: bytes=%d-\r\n"\"\r\n"// sprintf(pHttpRequest, FORMAT_HTTP_GET_REQUEST, pFileUrl, pHost, pRefer, lFileOffset);// 发送请求lpBufTemp = (LPBYTE)pHttpRequest;dwDataLen = strlen(pHttpRequest);dwSentTotal = 0;bRet = true;while (dwSentTotal < dwDataLen){int iSent = send(scSocket, (const char*)(lpBufTemp+dwSentTotal), dwDataLen-dwSentTotal, 0);if (iSent == 0){bRet = false;break;}else if (iSent == SOCKET_ERROR){bRet = false;break;}else{dwSentTotal += iSent;}}// 接收HTTP返回数据iRecvedTotal = 0;while (true){iRecv = recv(scSocket, pHttpResponse+iRecvedTotal, iRecvBufSize-iRecvedTotal, 0);if (iRecv == 0 || iRecv == SOCKET_ERROR){return 7;}iRecvedTotal += iRecv;// 连续找两个\r\n表示结束pSplitStr = "\r\n\r\n";pHeaderEndPos = strstr(pHttpResponse, pSplitStr);if (pHeaderEndPos != NULL){pHeaderEndPos += strlen(pSplitStr);break;}if (iRecvBufSize == iRecvedTotal){return 8;}}// 解析返回pLastPos = strchr(pHttpResponse, ' ');if (pLastPos == NULL){return 9;}pLastPos += 1;pEndPos = strstr(pLastPos, "\r\n");strncpy(pTempBuf, pLastPos, pEndPos-pLastPos);pLastPos = strchr(pTempBuf, ' ');if (pLastPos != NULL){pTempBuf[pLastPos-pTempBuf] = '\0';}iRetCode = atoi(pTempBuf);// switch (iRetCode){case 301:case 302:{// const char* pLocationStr = "Location: ";// 得到重定向后的地址pLastPos = strstr(pHttpResponse, pLocationStr);if (pLastPos == NULL){return 8;// 无法获取到重定向后的地址}pLastPos += strlen(pLocationStr);//pEndPos = strstr(pLastPos, "\r\n");// strcpy(pRefer, pHost);//memset(pHost, 0, iUrlBufSize);strncpy(pHost, pLastPos,  pEndPos-pLastPos);//closesocket(scSocket);scSocket = INVALID_SOCKET;// goto tagDown;}break;case 200:case 206:{// 得到数据的大小const char* pContentLength = "Content-Length: ";const char* pEndPos = NULL;int iHeaderLen = 0;int iDataLen = 0;bool bChunkMode = false;pLastPos = strstr(pHttpResponse, "Content-Range: ");if (pLastPos == NULL){bUseBreakMode = false;}else{bUseBreakMode = true;}// strcpy(pTempFileUrl, localfile);strcat(pTempFileUrl, ".tmp");// if (bUseBreakMode){// 读取断点位置strcpy(pBreakFileUrl, localfile);strcat(pBreakFileUrl, "_brk");fpBreakFile = fopen(pBreakFileUrl, "rb+");if (!fpBreakFile){// fpBreakFile = fopen(pBreakFileUrl, "wb+");//remove(pTempFileUrl);// 用写入的模式打开文件fpTempFile = fopen(pTempFileUrl, "wb+");}else{// 打开临时文件fpTempFile = fopen(pTempFileUrl,"rb+");if (!fpTempFile) {// 临时文件打开失败fpTempFile = fopen(pTempFileUrl, "wb+");if (!fpTempFile){return 4;}//lFileOffset = 0;}else{fscanf(fpBreakFile,"%d" , &lFileOffset);fseek(fpBreakFile, lFileOffset, SEEK_SET);}}}// pLastPos = strstr(pHttpResponse, pContentLength);if (pLastPos == NULL){// 判断是否为分块模式const char* pTransferEncoding = "Transfer-Encoding: ";const char* pChunkStr = "chunked";pLastPos = strstr(pHttpResponse, pContentLength);if (pLastPos == NULL){return 8;}pLastPos += strlen(pTransferEncoding);if (strnicmp(pLastPos, pChunkStr, strlen(pChunkStr)) != 0){return 9;}bChunkMode = true;return 12;}else{pLastPos += strlen(pContentLength);// 解析返回pSplitStr = "\r\n";pEndPos = strstr(pLastPos, "\r\n");strncpy(pTempBuf, pLastPos, pEndPos-pLastPos);pTempBuf[pEndPos-pLastPos] = '\0';iTotalDataSize = atoi(pTempBuf);}// iHeaderLen = (pHeaderEndPos - pHttpResponse);iDataLen = iRecvedTotal - iHeaderLen;if (iDataLen > 0){if (bChunkMode){return 12;}else{size_t nSize = 0;iRecvedFileBytes += iDataLen;lFileOffset += iDataLen;// 将数据写入文件nSize = fwrite(pHeaderEndPos, iDataLen, 1, fpTempFile);fflush(fpTempFile);// if (bUseBreakMode){// 写断点信息rewind(fpBreakFile);fprintf(fpBreakFile,"%d", lFileOffset);fflush(fpBreakFile);}}}// while (true){// 接收数据iRecv = recv(scSocket, pHttpResponse, iRecvBufSize, 0);if (iRecv == 0){return 10;}else if (iRecv == SOCKET_ERROR){return 11;}else{iRecvedTotal += iRecv;// if (bChunkMode){return 12;}else{iRecvedFileBytes += iRecv;lFileOffset += iRecv;// fwrite(pHttpResponse, iRecv, 1, fpTempFile);fflush(fpTempFile);// if (bUseBreakMode){// 写断点信息rewind(fpBreakFile);fprintf(fpBreakFile,"%d", lFileOffset);fflush(fpBreakFile);}// 写文件if (iRecvedFileBytes == iTotalDataSize){int iRet = 0;//// if (bUseBreakMode){fclose(fpBreakFile);fpBreakFile = NULL;// remove(pBreakFileUrl);}// remove(localfile);//fclose(fpTempFile);fpTempFile = NULL;// for (i=0;;){iRet = rename(pTempFileUrl, localfile);if (iRet != 0){if (++i > 10){return 13;}Sleep(1000);continue;}break;}// return 0;}}}}//}break;default:return 9;}}__finally{// 释放资源free(pHost);free(pRefer);free(pFileUrl);free(pHttpRequest);free(pHttpResponse);free(pTempBuf);if (fpBreakFile){fclose(fpBreakFile);}if (fpTempFile){fclose(fpTempFile);}}return -1;}


0 0
原创粉丝点击