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个字母。接着打开可以火狐的开发者网络这一功能。并且点击发送文件后,可以在消息头上看到如下信息。

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

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

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

时间: 2024-11-18 14:23:08

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

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

一.引言 欢迎大家来到和我一起编写Http服务器实现文件的上传和下载,现在我稍微回顾一下之前我说的,第一.二章说明说明了整体的HTTP走向,第三章实现底层的网络编程.接着这一章我想给大家讲的是请求获取,和响应发送的内容.这里主要讲解的响应内容,为什么?因为我们编写的是一个与浏览器交互的HTTP服务器,所以大多数的情况下我们只进行被动的应答. 这就是一种"提问--回答"的问题.其实在讲解这章的时候,我本来准备给大家讲解一下Linux一些信号中断的问题.因为在网络层发送的时候,系统会发送一

C# 之 FTP服务器中文件上传与下载(三)

通过上一篇博客<C# 之 FTP服务器中文件上传与下载(二)>,我们已经实现将文件上传到我们创建的FTP服务器.今天我们就一起来看看怎么样实现从FTP服务器中下载我们所需要的文件.         我们想实现的效果是在页面上有一个超链接,超链接显示为我们想要下载的文件名.点击该文件名进入下载页面.首先我们在前台插入一个超链接,但是这个超链接为后台拼接的超链接. using System; using System.Collections.Generic; using System.Linq;

C# 之 FTP服务器中文件上传与下载(四)

        通过上一篇博客<C# 之 FTP服务器中文件上传与下载(三)>,我们已经实现将文件从我们创建的FTP服务器中下载到本地.今天就最后给大家讲解一下怎么对FTP中的文件进行重命名和删除操作. 首先在前台添加两个重命名和删除的按钮 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Defaul

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

一.引言 大家都知道web编程的协议就是http协议,称为超文本传输协议.在J2EE中我们可以很快的实现一个Web工程,但在C++中就不是非常的迅速,原因无非就是底层的socket网络编写需要自己完成,上层的http协议需要我们自己完成,用户接口需要我们自己完成,如何高效和设计一个框架都是非常困难的一件事情.但这些事情Java已经在底层为我们封装好了,而我们仅仅只是在做业务层上的事情吧了. 在本Http服务器实现中,利用C++库和socket原套接字编程和pthread线程编写.拒绝使用第三方库

java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息

1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html https://www.cnblogs.com/longyg/archive/2012/06/25/2561332.html https://www.cnblogs.com/qdwyg2013/p/5650764.html#top 引入jar包的maven依赖如下所示:

限制上传大小、用COS实现文件上传与下载 五(63)

一 限制上传大小 1:限制总文件的大小 .    如 上传10文件,设置最多总上传大小为100M. void setSizeMax(long sizeMax)           Sets the maximum allowed size of a complete request, as opposed to setFileSizeMax(long). 2:设置第每一个文件的大小 ,如果设置每 一个文件大小10M.  void setFileSizeMax(long fileSizeMax)

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

一.引言 欢迎大家接着看我的博客,如何大家有什么想法的话回复我哦,闲话不多聊了,接着上一讲的内容来说吧,在上一节中已经讲到了请求头字符串的解析,并且在解析中我我们已经获取了url.就是上节中提到的/doing.当浏览器发送了/doing请求后,这是的与服务器的连接并没有中断,原因无他,就是浏览器等待接受服务端发来的信息,然后他对信息进行解析并显示在浏览器界面上.在编写Http服务器时的C/S结构时,我只编写服务端server,客户端直接用现成的浏览器即可. 当服务端找到浏览器需要的内容的时候,现

Android与Asp.Net Web服务器的文件上传下载BUG汇总【更新】

遇到的问题: 1.java.io.IOException: open failed: EINVAL (Invalid argument)异常,在模拟器中的sd卡创建文件夹和文件时报错 出错原因可能是:(1)文件名称中含有不符合规范的字符,比如“:”,“?”或者空格等.(2)需要先创建文件夹目录再创建文件,不能直接创建文件. 2. android.os.NetworkOnMainThreadException异常,从服务器请求数据后,写入文件时报错 出错原因:在主线程内执行了访问http的操作,最

JavaWeb学习总结(五十)——文件上传和下载

在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,stru