欢迎光临
我们一直在努力

Http服务器实现文件上传与下载(五)

一、引言

     欢迎大家和我一起编写Http服务器实现文件的上传和下载,现在我回顾一下在上一章节中提到的一些内容,之前我已经提到过文件的下载,在文件的下载中也提到了文件的续下载只需要在响应头中填写Content-Range这一字段,并且服务器的文件指针指向读取的指定位置开始读取传输。在这一章节中我讲讲解文件的上传这一功能,讲完这一章节,大致的功能也全部完成,接着就是上面文件控制模块和一些资源模块。

     在文件的上传中主要以httprequest类为主,在考虑文件的上传时我一点迷惑,到底把文件的上传功能是放到HttpResponse下还是在HttpRequest下,毕竟HttpResponse中有一些相应的文件下载功能,在添加一个文件上传功能也不为过。但是我最终还是选择在HttpRequest中,原因是我主要是HttpResponse作为是服务器到浏览器发送内容,而HttpRequest作为浏览器到服务器发送内容。这样下载和上传的功能就分别坐落在了HttpResponse和HttpRequest上了。

在完成功能上的归属问题后,接着直接上代码,在文件的上传中,涉及到C++流。在这里其实用到不是很多的内容,但是这却是C++一个重要的一大块内容。有时间和大家在一起复习这一块内容。好了,接着上代码咯,上一章的内容有设计一些HttpRequest的代码,没有全部的包括进去。

二、HttpRequest

头文件(include/httprequest.h)

 1 #ifndef HTTPREQUEST_H  2 #define HTTPREQUEST_H  3 #include "socket.h"  4 #include <map>  5 #include <string>  6 #include <fstream>  7 namespace Http{  8 class HttpRequest{  9 public: 10 HttpRequest(TCP::Socket &c); 11 virtual ~HttpRequest(); 12 std::string getMethod() const; 13 std::string getUrl() const; 14 std::string getHost() const; 15 std::map<std::string,std::string> getHeader(int confd) ; 16 ssize_t upload(int confd,std::string filename); 17 protected: 18 private: 19 std::string method; 20 std::string url; 21 std::string host; 22 TCP::Socket &s; 23  }; 24 } 25 #endif // HTTPREQUEST_H

源文件(src/httprequest.cpp)

 1 #include "httprequest.h"  2 #include "utils.h"  3 namespace Http{  4 HttpRequest::HttpRequest(TCP::Socket &c):s(c){  5  }  6  7 HttpRequest::~HttpRequest(){  8  }  9 std::map<std::string,std::string> HttpRequest::getHeader(int confd){ 10 char recvbuf[1024]; 11 memset(recvBuf,0,sizeof(recvBuf)); 12 s.server_read(confd,recvBuf,1024); 13 std::cout<<recvBuf<<std::endl; 14 std::map<std::string,std::string> mp =Utils::parseHeader(recvBuf); 15 method =mp["Method"]; 16 url=mp["Url"]; 17 host=mp["Host"]; 18 return mp; 19  } 20 ssize_t HttpRequest::upload(int confd,std::string filename){ 21 char buf[1024]; 22 size_t n=0; 23 ssize_t nread=0; 24 std::string boundary; 25 std::string file; 26  std::ofstream outStream; 27 int readlineCount=1; 28 while(1){ 29 memset(buf,0,sizeof(buf)); 30 n=s.server_readline(confd,buf,sizeof(buf)); 31 if(readlineCount==1){ 32 boundary=std::string(buf,buf+strlen(buf)-2); 33 boundary+="--\r\n"; 34 std::cout<<boundary<<std::endl<<boundary.size(); 35 }else if(readlineCount==2){ 36 int i=n; 37 while(buf[i]!='='){ 38 if((buf[i]>='0'&&buf[i]<='9') 39 ||(buf[i]>='a'&&buf[i]<='z') 40 ||(buf[i]>='A'&&buf[i]<='Z') 41 ||(buf[i]=='.')) 42 i--; 43 else{ 44 buf[i]='*'; 45 i--; 46  } 47  } 48 file=std::string(buf+i+2,buf+n-3); 49 }else if(readlineCount==3){ 50 std::string rw; 51 rw=std::string(buf,buf+strlen(buf)); 52 int pos=rw.find('/'); 53 rw=rw.substr(0,pos); 54 filename=filename+file; 55 if(rw=="Content-Type: text") 56  outStream.open(filename.c_str()); 57 else{ 58  outStream.open(filename.c_str(),std::ios::binary); 59 std::cout<<"ios::binary"<<std::endl; 60  } 61 }else if(readlineCount==4){ 62 memset(buf,0,sizeof(buf)); 63 while(1){ 64 n=s.server_readn(confd,buf,sizeof(buf)); 65 if(n==boundary.size()&&strcmp(buf,boundary.c_str())==0){ 66 goto exit; 67  } 68 nread+=n; 69 if(buf[n-1]==0){ 70 outStream.write(buf,n-1); 71 }else{ 72  outStream.write(buf,n); 73  } 74  } 75  } 76 readlineCount++; 77  } 78  exit: 79  outStream.close(); 80  s.server_close(confd); 81 return nread; 82  } 83 std::string HttpRequest::getMethod() const{ 84 return method; 85  } 86 std::string HttpRequest::getUrl() const{ 87 return url; 88  } 89 std::string HttpRequest::getHost() const{ 90 return host; 91  } 92 }

     好了上传文件的代码也已经出来了,现在就是对其稍微的解释一下把。在解释代码之前先看一下我们在点击上传文件按钮的时候,浏览器给服务器发送的内容是什么,比如我有一个test.txt的文本文件(这里采用文件文件是为了好查看内容,其实二进制文件也是一致的)。test.txt文件的内容只有一行就是aaabbb这6个字母。接着打开可以火狐的开发者网络这一功能。并且点击发送文件后,可以在消息头上看到如下信息。

Http服务器实现文件上传与下载(五)

    这些内容在之前的章节已经讲过了,这里就不重复了,并且点击参数这一选项可以看到如下信息。

Http服务器实现文件上传与下载(五)

     在这里第1,2行是请求头的内容,接着一行空行之后是请求体4-9行。看到请求体的内容不是直接是test.txt的内容。显示‘--23469111452’为开头,拜师这个是文本的分隔符。前面固定一段'-',加上一个浏览器自动产生的数据。并且一个文件的解释也是这样,只是数字后面多了2个'-'。在第5,6行是对上传的文件的描述。接着是一行空行。第8行开始就是文件的内容了。知道这个请求体后,很容易的就可以写出代码。上面的的upload中readlineCount变量就是起到定位功能。看服务器已经接收到那一行了,这里s.server_readn这个行数之间没有提交,现在的代码段一直在修改,所以有些与博客有点差别,大体上还是一致的。

      写到这里,基本上完成了HttpServer这一文件上传和下载功能。接着就是组合这些某块。将在下一章《Http服务器实现文件上传与下载(六)》中进行讲解。

 

  • 海报
海报图正在生成中...
赞(1) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《Http服务器实现文件上传与下载(五)》
文章链接:https://www.456zj.com/5634.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址