使用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 选中左边需要上传的文件,然后拖到右边,等待 ...
随机推荐
- Linux大文件传输(转)
我们经常需要在机器之间传输文件.比如备份,复制数据等等.这个是很常见,也是很简单的.用scp或者rsync就能很好的完成任务.但是如果文件很大,需要占用一些传输时间的时候,怎样又快又好地完成任务就很重 ...
- Maven使用--打包和运行
将项目进行编译.测试后,下一个重要步骤就是打包.简单执行命令mvn clean package进行打包.Maven会在打包前执行编译.测试等操作. 在打包后,执行安装任务install ...
- 执行sh文件 进行MongoDB的业务逻辑导入
将从HDFS中的数据转化为Json格式写入文件后,十个文件的文件名为 文件名_01 ...._02 ....03格式. 编写个简单的sh文件 通过for do循环让i+1 文件名对应上就可以的- -执 ...
- POJ2226 Muddy Fields 二分匹配 最小顶点覆盖 好题
在一个n*m的草地上,.代表草地,*代表水,现在要用宽度为1,长度不限的木板盖住水, 木板可以重叠,但是所有的草地都不能被木板覆盖. 问至少需要的木板数. 这类题的建图方法: 把矩阵作为一个二分图,以 ...
- mapreduce执行流程
角色描述:JobClient:执行任务的客户端JobTracker:任务调度器TaskTracker:任务跟踪器Task:具体的任务(Map OR Reduce) 从生命周期的角度来看,mapredu ...
- ylbtech-LanguageSamples-Threading(线程处理)
ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Threading(线程处理) 1.A,示例(Sample) 返回顶部 “线程处理”示例 ...
- Ubuntu Server如何配置SFTP
SH File Transfer Protocol是一个比普通FTP更为安全的文件传输协议.(参考资料:http://en.wikipedia.org/wiki/SSH_File_Transfer_P ...
- HTTP Response中的Status-Code
1XX : 通知信息.请求被接收,继续处理2XX : 成功.请求动作被成功接收.理解和接受3XX : 重定向.需要其他的动作来完成这个请求4XX : 客户端错误.请求包含错误的语法或者缺少语法5XX ...
- CentOS 安装 Chrome
cd /etc/yum.repos.d/ vi google.repo [gogle] name=Google-x86_64 baseurl=http://dl.google.com/linux/ ...
- codeblocks安装后无法编译
codeblocks安装后无法编译: 解决办法: 1.下载自带编译器的codeblock安装包. 2.安装完后.修改配置 (1)打开软件,选择setting->Compiler (2)在编译器设 ...