• 使用HTTP协下载文件


    通过发送HTTP请求,下载文件

    头文件:

     1 #ifndef __HTTP__
     2 #define __HTTP__
     3 
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <string>
     7 #include <winsock.h>
     8 
     9 using namespace std;
    10 
    11 /**
    12  * URL相关数据
    13  */
    14 typedef struct _URLData {
    15     string url;     // 完整的url地址
    16     string path;    // 文件路径
    17     string host;    // 主机名
    18     string ip;      // 点分隔的ip
    19     int    port;    // 端口
    20     string resName; // 资源名字
    21 } URLData;
    22 
    23 /**
    24  * 解析url
    25  */
    26 void parseURL(string url, URLData* data);
    27 
    28 /**
    29  * 链接http服务器
    30  */
    31 bool connectHttpServer(int socketId, string ip, int port);
    32 
    33 /**
    34  * 生成请求文本
    35  */
    36 void generateRequestTxt(URLData* data, string* requestTxt);
    37 
    38 /**
    39  * 发送http请求
    40  */
    41 bool sendHttpRequest(int socketId, string* requestTxt);
    42 
    43 /**
    44  * 接受响应数据
    45  */
    46 void recvHttpResponse(int socketId, string* responseTxt);
    47 
    48 /**
    49  * 保存http数据
    50  */
    51 bool saveHttpData(string* responseTxt, string filePath = "", string fileName = "");
    52 
    53 /**
    54  * 获取http资源
    55  */
    56 bool getHttpResource(string url, string filePath = "", string fileName = "");
    57 
    58 #endif

    代码文件:

      1 #include "http.h"
      2 #include "DNS/DNS.h"
      3 #include "time.h"
      4 
      5 /**
      6  * 解析url
      7  */
      8 void parseURL(string url, URLData* data)
      9 {
     10     int startPos = 0;
     11     string begin = url.substr(0, 4);
     12     if (begin == "http") {
     13         startPos = 7;
     14     }
     15 
     16     int i = startPos;
     17     int lastSplitPos = 0;
     18     for (int len = url.length(); i<len; i++) {
     19         unsigned char ch = url.at(i);
     20 
     21         if (ch == 47) {
     22             if (data->host.length() == 0) {
     23                 data->host = url.substr(startPos, i - startPos);
     24                 data->path = url.substr(i, url.length() - i);
     25 
     26                 break;
     27             }
     28 
     29             lastSplitPos = i;
     30         }
     31     }
     32     // data->path = url.substr(iPath, url.length() - iPath);
     33     data->url = url;
     34     data->port = 80;
     35 
     36     int resNameLastPos = url.length()-1;
     37     int resNameFirstPos = 0;
     38     for (int i = url.length()-1; i>=0; i--) {
     39         unsigned char ch = url.at(i);
     40         
     41         if (ch == '.')
     42             resNameLastPos = i;
     43         else if (ch == '/') {
     44             resNameFirstPos = i + 1;
     45             break;
     46         }
     47     }
     48     data->resName = url.substr(resNameFirstPos, resNameLastPos - resNameFirstPos);
     49 }
     50 
     51 /**
     52  * 链接HTTP服务器
     53  */
     54 bool connectHttpServer(int socketId, string ip, int port)
     55 {
     56     // 初始套接字化地址
     57     struct sockaddr_in serverAddr;
     58     memset(&serverAddr, 0, sizeof(serverAddr));
     59     serverAddr.sin_family = AF_INET;
     60     serverAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
     61     serverAddr.sin_port = htons(port);
     62 
     63     if (connect(socketId, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
     64         return false;
     65     }
     66     return true;
     67 }
     68 
     69 /**
     70  * 生成请求文本
     71  */
     72 void generateRequestTxt(URLData* data, string* requestTxt)
     73 {
     74     requestTxt->append("GET "); requestTxt->append(data->path); requestTxt->append(" HTTP/1.1
    ");
     75     requestTxt->append("Host: "); requestTxt->append(data->host); requestTxt->append("
    ");
     76     requestTxt->append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    "); 
     77     requestTxt->append("Accept-Language: zh-CN,zh;q=0.8
    ");
     78     requestTxt->append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36
    ");
     79     requestTxt->append("Accept-Encoding: deflate,sdch
    ");
     80     requestTxt->append("Connection: close
    
    ");
     81 }
     82 
     83 /**
     84  * 发送http请求
     85  */
     86 bool sendHttpRequest(int socketId, string* requestTxt)
     87 {
     88     int sendBytes = send(socketId, requestTxt->c_str(), requestTxt->length(), 0);
     89     return sendBytes > 0;
     90 }
     91 
     92 /**
     93  * 接受响应数据
     94  */
     95 void recvHttpResponse(int socketId, string* responseTxt)
     96 {
     97     char buff[1024];
     98 
     99     int recvBytes = 0;
    100     while ((recvBytes = recv(socketId, buff, 1024, 0)) > 0) {
    101         responseTxt->append(buff, recvBytes);
    102     }
    103 }
    104 
    105 /**
    106  * 保存http数据
    107  */
    108 bool saveHttpData(string* responseTxt, string filePath, string fileName)
    109 {
    110     if (fileName == "") {
    111         char _fileName[100];
    112         sprintf(_fileName, "%lld", time(0));
    113         fileName = _fileName;
    114     }
    115 
    116     string fileExt = ".";
    117 
    118     int i = 0, len = 0;
    119     for (i = 0, len = responseTxt->length(); i<len; i++) {
    120         unsigned char ch = responseTxt->at(i);
    121 
    122         if (ch == 'C') {
    123             unsigned char metaKey[13], typeMetaKey[13] = "Content-Type";
    124             memset(metaKey, 0, 13);
    125             memcpy(metaKey, responseTxt->c_str() + i, 12);
    126 
    127             string metaValue;
    128             if ( strcmp((char*)metaKey, (char*)typeMetaKey) == 0 ) {
    129                 for (int j = i+13;;j++) {
    130                     unsigned char ch = responseTxt->at(j);
    131 
    132                     metaValue.push_back(ch);
    133                     if (ch == '
    ') {
    134                         for (int k = 0, len = metaValue.length(); k<len; k++) {
    135                             if (metaValue.at(k) == '/') {
    136                                 fileExt.append( metaValue.substr(k+1, metaValue.length() - k - 2) );
    137                                 fileName.append(fileExt);
    138 
    139                                 break;
    140                             }
    141                         }
    142 
    143                         break;
    144                     }
    145                 }
    146             }
    147         }
    148 
    149         if (ch == '
    ' && 
    150             responseTxt->at(i+1) == '
    ' &&
    151             responseTxt->at(i+2) == '
    ' &&
    152             responseTxt->at(i+3) == '
    ') {
    153             i += 4;
    154             break;
    155         }
    156     }
    157 
    158     FILE* fp = fopen((filePath + fileName).c_str(), "wb+");
    159     if (fp) {
    160         fwrite(responseTxt->c_str() + i, 1, responseTxt->length() - i, fp);
    161         fclose(fp);
    162 
    163         return true;
    164     }
    165     return false;
    166 }
    167 
    168 /**
    169  * 获取http资源
    170  */
    171 bool getHttpResource(string url, string filePath, string fileName)
    172 {
    173     printf("-------------------------------------
    ");
    174 
    175     int socketId = socket(AF_INET, SOCK_STREAM, 0);
    176     if (socketId == INVALID_SOCKET) {
    177         printf("Create sokcet failed
    ");
    178 
    179         return false;
    180     }
    181 
    182     // 解析url数据
    183     URLData data;
    184     parseURL(url, &data);
    185 
    186     // 获取DNS信息
    187     if (!getIPAddrByDNS(data.host, &data.ip)) {
    188         printf("Get ip(%s) from DNS server failed
    ", data.host.c_str());
    189 
    190         return false;
    191     }
    192 
    193     // 生成请求文本
    194     string requestTxt;
    195     generateRequestTxt(&data, &requestTxt);
    196 
    197     // 链接服务器
    198     if (!connectHttpServer(socketId, data.ip, data.port)) {
    199         printf("Connect http server failed, ip:%s
    ", data.ip.c_str());
    200 
    201         return false;
    202     }
    203 
    204     printf("Send http request:
    %s
    ", requestTxt.c_str());
    205 
    206     // 发送请求
    207     if (!sendHttpRequest(socketId, &requestTxt)) {
    208         printf("Send http request failed
    ");
    209 
    210         return false;
    211     }
    212 
    213     // 接受响应
    214     string responseTxt;
    215     recvHttpResponse(socketId, &responseTxt);
    216 
    217     printf("Recive http response:
    %s
    ", responseTxt.c_str());
    218 
    219     // 保存数据
    220     if (!saveHttpData(&responseTxt, filePath, (fileName.length() == 0) ? data.resName : fileName)) {
    221         printf("Save response data failed
    ");
    222         return false;
    223     }
    224 
    225     closesocket(socketId);
    226 
    227     printf("-------------------------------------
    ");
    228 
    229     return true;
    230 }

    使用方法:

    1 string url = "http://static.youku.com/index/img/master.png";
    2 getHttpResource(url);
  • 相关阅读:
    Java编程思想小笔记
    JAVA中的访问权限
    重写equals、hashCode
    JAVA核心技术I之接口与内部类
    JAVA核心技术I之继承
    javascript日志-array数组去重
    vue练习项目
    vue日志-axios跨域获取豆瓣api
    在vue-cli中安装scss,且可以全局引入scss的步骤
    css参考手册
  • 原文地址:https://www.cnblogs.com/iRidescent-ZONE/p/4169361.html
Copyright © 2020-2023  润新知