使用HTTP协下载文件
通过发送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协下载文件的更多相关文章
- Java远程下载文件到本地(http协议和ssh2协议)
Java中java.io包为我们提供了输入流和输出流,对文件的读写基本上都依赖于这些封装好的关于流的类中来实现.前段时间遇到了以下两种需求: 1.与某系统对接,每天获取最新的图片并显示在前端页面.该系 ...
- [转]python3之paramiko模块(基于ssh连接进行远程登录服务器执行命令和上传下载文件的功能)
转自:https://www.cnblogs.com/zhangxinqi/p/8372774.html 阅读目录 1.paramiko模块介绍 2.paramiko的使用方法 回到顶部 1.para ...
- Java下载文件(流的形式)
@RequestMapping("download") @ResponseBody public void download(HttpServletResponse respons ...
- 使用批处理文件在FTP服务器 上传下载文件
1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt 192.168.1.1 建立一个 ...
- 通过form表单的形式下载文件。
在项目中遇到问题,要求动态拼接uri下载文件.但是由于项目的安全拦截导致window.location.href 和 window.open等新建窗口的方法都不行. 无意间百度到了通过form表单来下 ...
- SecureCRT上传和下载文件
SecureCRT上传和下载文件(下载默认目录) SecureCR 下的文件传输协议有ASCII .Xmodem .Ymodem .Zmodem ASCII:这是最快的传输协议,但只能传送文本文件. ...
- HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
今天,在vs2013中新建了一个placard.json文件,当我用jq读取它的时候,去提示404,直接在浏览器访问这个文件,提示: HTTP 错误 404.3 – Not Found 由于扩展配置问 ...
- FTP下载文件失败
这几天的定时任务下载文件的脚本失败了. 于是手工执行测试,发现报550 Permission denied. Passive mode refused. 意思就是被动模式下,没有权限获取文件. 解决方 ...
- 如何使用FileZilla上传和下载文件
一.使用FileZilla上传文件 1 打开 FileZilla 按照如下图所示,填写远程 Linux 的 IP ,用户名,密码,还有端口号(默认22) 2 选中左边需要上传的文件,然后拖到右边,等待 ...
随机推荐
- hibernateUtils
hibernate3.x版本 package hibernate_01; import org.hibernate.Session; import org.hibernate.SessionFacto ...
- Redis 内存使用优化与存储
Redis 常用数据类型 Redis 最为常用的数据类型主要有以下五种: • String • Hash • List • Set • Sorted set 在具体描述这几种数据类型之前,我们先通过一 ...
- sparkStreaming与Kafka整合
createStream那几个参数折腾了我好久..网上都是一带而过,最终才搞懂..关于sparkStreaming的还是太少,最终尝试成功... 首先启动zookeeper ./bin/zookeep ...
- 你应该知道的jQuery技巧
帮助提高你jQuery应用的简单小技巧. 回到顶部按钮 图片预加载 判断图片是否加载完 自动修补破损图像 Hover切换class类 禁用输入 停止正在加载的链接 toggle fade/slide ...
- Java多线程之DaemonThreadFactory
通过DaemonThreadFactory创建后台线程池 另外:如果是后台线程创建的线程,将都是后台线程. package wzh.daemon; import java.util.concurren ...
- VB EOF
源地址: http://zhidao.baidu.com/link?url=zs49D5HzAgoyd3siE44oLbJlVLsWGpf1zqqvXVWZg_ZGXbFY7BgKFDpCqJdANO ...
- win10,软件, 发布者不受信任怎么办
这个方法比较管用:右键单击windows左下角,弹出右击菜单选择‘命令提示符(管理员)(A)’,然后用DOS命令安装程序.就可以了 PS:win10的cmd可以直接复制粘贴了.
- 织梦CMS站点favicon.ico图标的放置
1.在线制作一个ico图标,推荐制作网站:http://ico.55.la/.制作好后,将favicon.ico图标放在站点模板默认目录下的images文件夹里. 2.在index.htm的<h ...
- IIS6.0中布署MVC站点(转)
昨晚我写的API上线,API是vs2010 + MVC4开发的,需要布署到windows 2003 server + IIS6.0的环境中,之前一直是布在IIS7.0,比较熟悉, 换到IIS6.0,添 ...
- vmware虚拟机挂起后无法再恢复(转)
之前一直使用vmware调试程序,但有一天它被挂起后,就一直无法恢复. 提示: 无法获取该配置文件上的排他锁 另一个VMware进程可能正在使用此配置文件. 后来在google里查了一下,发现其实是一 ...