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

头文件:

 #ifndef __HTTP__
#define __HTTP__ #include <stdio.h>
#include <stdlib.h>
#include <string>
#include <winsock.h> using namespace std; /**
* URL相关数据
*/
typedef struct _URLData {
string url; // 完整的url地址
string path; // 文件路径
string host; // 主机名
string ip; // 点分隔的ip
int port; // 端口
string resName; // 资源名字
} URLData; /**
* 解析url
*/
void parseURL(string url, URLData* data); /**
* 链接http服务器
*/
bool connectHttpServer(int socketId, string ip, int port); /**
* 生成请求文本
*/
void generateRequestTxt(URLData* data, string* requestTxt); /**
* 发送http请求
*/
bool sendHttpRequest(int socketId, string* requestTxt); /**
* 接受响应数据
*/
void recvHttpResponse(int socketId, string* responseTxt); /**
* 保存http数据
*/
bool saveHttpData(string* responseTxt, string filePath = "", string fileName = ""); /**
* 获取http资源
*/
bool getHttpResource(string url, string filePath = "", string fileName = ""); #endif

代码文件:

 #include "http.h"
#include "DNS/DNS.h"
#include "time.h" /**
* 解析url
*/
void parseURL(string url, URLData* data)
{
int startPos = ;
string begin = url.substr(, );
if (begin == "http") {
startPos = ;
} int i = startPos;
int lastSplitPos = ;
for (int len = url.length(); i<len; i++) {
unsigned char ch = url.at(i); if (ch == ) {
if (data->host.length() == ) {
data->host = url.substr(startPos, i - startPos);
data->path = url.substr(i, url.length() - i); break;
} lastSplitPos = i;
}
}
// data->path = url.substr(iPath, url.length() - iPath);
data->url = url;
data->port = ; int resNameLastPos = url.length()-;
int resNameFirstPos = ;
for (int i = url.length()-; i>=; i--) {
unsigned char ch = url.at(i); if (ch == '.')
resNameLastPos = i;
else if (ch == '/') {
resNameFirstPos = i + ;
break;
}
}
data->resName = url.substr(resNameFirstPos, resNameLastPos - resNameFirstPos);
} /**
* 链接HTTP服务器
*/
bool connectHttpServer(int socketId, string ip, int port)
{
// 初始套接字化地址
struct sockaddr_in serverAddr;
memset(&serverAddr, , sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
serverAddr.sin_port = htons(port); if (connect(socketId, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
return false;
}
return true;
} /**
* 生成请求文本
*/
void generateRequestTxt(URLData* data, string* requestTxt)
{
requestTxt->append("GET "); requestTxt->append(data->path); requestTxt->append(" HTTP/1.1\r\n");
requestTxt->append("Host: "); requestTxt->append(data->host); requestTxt->append("\r\n");
requestTxt->append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n");
requestTxt->append("Accept-Language: zh-CN,zh;q=0.8\r\n");
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\r\n");
requestTxt->append("Accept-Encoding: deflate,sdch\r\n");
requestTxt->append("Connection: close\r\n\r\n");
} /**
* 发送http请求
*/
bool sendHttpRequest(int socketId, string* requestTxt)
{
int sendBytes = send(socketId, requestTxt->c_str(), requestTxt->length(), );
return sendBytes > ;
} /**
* 接受响应数据
*/
void recvHttpResponse(int socketId, string* responseTxt)
{
char buff[]; int recvBytes = ;
while ((recvBytes = recv(socketId, buff, , )) > ) {
responseTxt->append(buff, recvBytes);
}
} /**
* 保存http数据
*/
bool saveHttpData(string* responseTxt, string filePath, string fileName)
{
if (fileName == "") {
char _fileName[];
sprintf(_fileName, "%lld", time());
fileName = _fileName;
} string fileExt = "."; int i = , len = ;
for (i = , len = responseTxt->length(); i<len; i++) {
unsigned char ch = responseTxt->at(i); if (ch == 'C') {
unsigned char metaKey[], typeMetaKey[] = "Content-Type";
memset(metaKey, , );
memcpy(metaKey, responseTxt->c_str() + i, ); string metaValue;
if ( strcmp((char*)metaKey, (char*)typeMetaKey) == ) {
for (int j = i+;;j++) {
unsigned char ch = responseTxt->at(j); metaValue.push_back(ch);
if (ch == '\r') {
for (int k = , len = metaValue.length(); k<len; k++) {
if (metaValue.at(k) == '/') {
fileExt.append( metaValue.substr(k+, metaValue.length() - k - ) );
fileName.append(fileExt); break;
}
} break;
}
}
}
} if (ch == '\r' &&
responseTxt->at(i+) == '\n' &&
responseTxt->at(i+) == '\r' &&
responseTxt->at(i+) == '\n') {
i += ;
break;
}
} FILE* fp = fopen((filePath + fileName).c_str(), "wb+");
if (fp) {
fwrite(responseTxt->c_str() + i, , responseTxt->length() - i, fp);
fclose(fp); return true;
}
return false;
} /**
* 获取http资源
*/
bool getHttpResource(string url, string filePath, string fileName)
{
printf("-------------------------------------\n"); int socketId = socket(AF_INET, SOCK_STREAM, );
if (socketId == INVALID_SOCKET) {
printf("Create sokcet failed\n"); return false;
} // 解析url数据
URLData data;
parseURL(url, &data); // 获取DNS信息
if (!getIPAddrByDNS(data.host, &data.ip)) {
printf("Get ip(%s) from DNS server failed\n", data.host.c_str()); return false;
} // 生成请求文本
string requestTxt;
generateRequestTxt(&data, &requestTxt); // 链接服务器
if (!connectHttpServer(socketId, data.ip, data.port)) {
printf("Connect http server failed, ip:%s\n", data.ip.c_str()); return false;
} printf("Send http request:\n%s\n", requestTxt.c_str()); // 发送请求
if (!sendHttpRequest(socketId, &requestTxt)) {
printf("Send http request failed\n"); return false;
} // 接受响应
string responseTxt;
recvHttpResponse(socketId, &responseTxt); printf("Recive http response:\n%s\n", responseTxt.c_str()); // 保存数据
if (!saveHttpData(&responseTxt, filePath, (fileName.length() == ) ? data.resName : fileName)) {
printf("Save response data failed\n");
return false;
} closesocket(socketId); printf("-------------------------------------\n"); return true;
}

使用方法:

 string url = "http://static.youku.com/index/img/master.png";
getHttpResource(url);

使用HTTP协下载文件的更多相关文章

  1. Java远程下载文件到本地(http协议和ssh2协议)

    Java中java.io包为我们提供了输入流和输出流,对文件的读写基本上都依赖于这些封装好的关于流的类中来实现.前段时间遇到了以下两种需求: 1.与某系统对接,每天获取最新的图片并显示在前端页面.该系 ...

  2. [转]python3之paramiko模块(基于ssh连接进行远程登录服务器执行命令和上传下载文件的功能)

    转自:https://www.cnblogs.com/zhangxinqi/p/8372774.html 阅读目录 1.paramiko模块介绍 2.paramiko的使用方法 回到顶部 1.para ...

  3. Java下载文件(流的形式)

    @RequestMapping("download") @ResponseBody public void download(HttpServletResponse respons ...

  4. 使用批处理文件在FTP服务器 上传下载文件

    1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt   192.168.1.1 建立一个 ...

  5. 通过form表单的形式下载文件。

    在项目中遇到问题,要求动态拼接uri下载文件.但是由于项目的安全拦截导致window.location.href 和 window.open等新建窗口的方法都不行. 无意间百度到了通过form表单来下 ...

  6. SecureCRT上传和下载文件

    SecureCRT上传和下载文件(下载默认目录) SecureCR 下的文件传输协议有ASCII .Xmodem .Ymodem .Zmodem ASCII:这是最快的传输协议,但只能传送文本文件. ...

  7. HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。

    今天,在vs2013中新建了一个placard.json文件,当我用jq读取它的时候,去提示404,直接在浏览器访问这个文件,提示: HTTP 错误 404.3 – Not Found 由于扩展配置问 ...

  8. FTP下载文件失败

    这几天的定时任务下载文件的脚本失败了. 于是手工执行测试,发现报550 Permission denied. Passive mode refused. 意思就是被动模式下,没有权限获取文件. 解决方 ...

  9. 如何使用FileZilla上传和下载文件

    一.使用FileZilla上传文件 1 打开 FileZilla 按照如下图所示,填写远程 Linux 的 IP ,用户名,密码,还有端口号(默认22) 2 选中左边需要上传的文件,然后拖到右边,等待 ...

随机推荐

  1. (微信API接口开发) 使用HttpWebRequest进行请求时发生错误:基础连接已关闭,发送时发生错误处理

    最近调试原来的微信模拟登陆时发生了“基础连接已关闭,发送时发生错误”的错误提示,原来都是好好的,只是很久没用了. 出错代码如下: HttpWebRequest req = (HttpWebReques ...

  2. 黄聪:WebBrowser执行和安装jQuery脚本(IEBrowse)

    上一文章说明了如何让 js 脚本访问 .NET 中的类, 这次希望给大家说明一下在任意页面中安装 jQuery 脚本, 并操作页面上的元素. 其实在第一篇关于 IEBrowser 的文章当中, 已经有 ...

  3. 黄聪:C#如何通过MeasureString、Graphics获取字符串的像素长度

    1.    使用g.MeasureString()获得 使用MeasureString测量出来的字符宽度,总是比实际宽度大一些,而且随着字符的长度增大,貌似实际宽度和测量宽度的差距也越来越大了.查了一 ...

  4. C++库大全(转)

    基础类1. Dinkumware C++ Library 参考站点:http://www.dinkumware.com P.J. Plauger编写的高品质的标准库.P.J. Plauger博士是Dr ...

  5. Java compiler level does not match the version of the installed Java project facet. springmvc1 和 Target runtime Apache Tomcat v7.0 is not defined.

    Java compiler level does not match the version of the installed Java project facet.springmvc1 : Targ ...

  6. adb上使用cp/mv命令的替代方法(failed on '***' - Cross-device link解决方法)

    今天把玩手头的那部Android手机时碰到一个问题,即因为权限问题无法将文件复制到/system/和/data/分区中,经过一番折腾后,算是解决了,在此记录一笔.本方所涉及到的命令输入,均用斜体字表示 ...

  7. WindowsForm应用程序调用WebService

    本文原创,如需转载,请标明源地址,谢谢合作!http://blog.csdn.net/sue_1989/article/details/6597078 本文的编写IDE为VSTS2008和.NET F ...

  8. 编写一个程序对Largest函数进行测试,找出一组数据的最大值

    源程序代码: import java.util.Scanner; public class findmax { public static void main(String[] args) { // ...

  9. 保存恢复临时信-Android 中使用onSaveInstanceState和onRestoreInstanceState

    在Activity中,有两个方法用于临时保存.恢复状态信息,这两个方法是: public void onSaveInstanceState(Bundle savedInstanceState); pu ...

  10. hadoop源代码解读

    http://blog.csdn.net/keda8997110/article/details/8474349