使用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 选中左边需要上传的文件,然后拖到右边,等待 ...
随机推荐
- Android二-.9.png
1.1px*1px,用于拉伸,应用于背景展示 2.一个复杂图片,拉伸纯色部分(上,左),不可拉伸部分,存放内容(下,右)
- (C#) 多线程修改布尔值, volatile
参考: https://msdn.microsoft.com/en-us/library/x13ttww7(VS.80).aspx http://stackoverflow.com/questions ...
- (C/C++) Callback Function 回调(diao)函数
原文: http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.php/c10557/Callback-Functions-Tutorial ...
- JMS的常用方法
import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; impor ...
- OAuth2.0_豆瓣登录_API错误返回码说明一览表[转]
转自: http://blog.unvs.cn/archives/douban-oauth-2.0-error_code.html 在遵循OAuth2.0协议,开始制作豆瓣过程中,经常会遇到以下两个错 ...
- 转--Android学习笔记-实用代码合集
http://blog.csdn.net/yf210yf/article/details/7295577 转载请注明原文出处:奔跑的蜗牛(袁方的技术博客)点击打开链接 一.当利用textview显示内 ...
- mapreduce任务中Shuffle和排序的过程
mapreduce任务中Shuffle和排序的过程 流程分析: Map端: 1.每个输入分片会让一个map任务来处理,默认情况下,以HDFS的一个块的大小(默认为64M)为一个分片,当然我们也可以设置 ...
- window下安装oracle数据库
Oracle 11g安装 1.解压下载的包,然后进入包内,点击setup.exe开始安装 . 2.出现如下:一般把那个小对勾取消,点击下一步进行, 弹出下图这个后点‘是’ 3.下图后,选择创建和配置数 ...
- android之蓝牙设备的使用01
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- code md5
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptograph ...