1, Introduction
Welcome to write it with me Http The server realizes file upload and download. Now I review some contents mentioned in the previous chapter. I have mentioned file download before. In file download, I also mentioned file continuous download, which only needs to be filled in the response header Content-Range This field, and the file pointer of the server points to the specified location for reading to start the read transfer. In this chapter, I will explain the function of file upload. After this chapter, the general functions will be completed, followed by the above file control module and some resource modules. In the upload of files, mainly HttpRequest Class. When considering file upload, I am a little confused. What is the file upload function HttpResponse Next or next HttpRequest Well, after all HttpResponse There are some corresponding file download functions in. It's not too much to add a file upload function. But I finally chose to HttpRequest The reason is that I am mainly HttpResponse Send content as server to browser, and HttpRequest Send content to the server as a browser. In this way, the download and upload functions are located separately HttpResponse and HttpRequest Yes.
After completing the functional attribution problem, then directly upload the code. In the file upload, it involves C + + stream. Here, it is not very practical, but it is an important piece of C + +. I have time to review this content with you. OK, then go to the code. In the previous chapter, there are some codes for designing HttpRequest, but not all of them are included.
2, HttpRequest
Header file (include/httprequest.h)
#ifndef HTTPREQUEST_H #define HTTPREQUEST_H #include "socket.h" #include <map> #include <string> #include <fstream> namespace Http{ class HttpRequest{ public: HttpRequest(TCP::Socket &c); virtual ~HttpRequest(); std::string getMethod() const; std::string getUrl() const; std::string getHost() const; std::map<std::string,std::string> getHeader(int confd) ; ssize_t upload(int confd,std::string filename); protected: private: std::string method; std::string url; std::string host; TCP::Socket &s; }; } #endif // HTTPREQUEST_H
Source file (src/httprequest.cpp)
#include "httprequest.h" #include "utils.h" namespace Http{ HttpRequest::HttpRequest(TCP::Socket &c):s(c){ } HttpRequest::~HttpRequest(){ } std::map<std::string,std::string> HttpRequest::getHeader(int confd){ char recvBuf[1024]; memset(recvBuf,0,sizeof(recvBuf)); s.server_read(confd,recvBuf,1024); std::cout<<recvBuf<<std::endl; std::map<std::string,std::string> mp =Utils::parseHeader(recvBuf); method =mp["Method"]; url=mp["Url"]; host=mp["Host"]; return mp; } ssize_t HttpRequest::upload(int confd,std::string filename){ char buf[1024]; size_t n=0; ssize_t nread=0; std::string boundary; std::string file; std::ofstream outStream; int readlineCount=1; while(1){ memset(buf,0,sizeof(buf)); n=s.server_readline(confd,buf,sizeof(buf)); if(readlineCount==1){ boundary=std::string(buf,buf+strlen(buf)-2); boundary+="--\r\n"; std::cout<<boundary<<std::endl<<boundary.size(); }else if(readlineCount==2){ int i=n; while(buf[i]!='='){ if((buf[i]>='0'&&buf[i]<='9') ||(buf[i]>='a'&&buf[i]<='z') ||(buf[i]>='A'&&buf[i]<='Z') ||(buf[i]=='.')) i--; else{ buf[i]='*'; i--; } } file=std::string(buf+i+2,buf+n-3); }else if(readlineCount==3){ std::string rw; rw=std::string(buf,buf+strlen(buf)); int pos=rw.find('/'); rw=rw.substr(0,pos); filename=filename+file; if(rw=="Content-Type: text") outStream.open(filename.c_str()); else{ outStream.open(filename.c_str(),std::ios::binary); std::cout<<"ios::binary"<<std::endl; } }else if(readlineCount==4){ memset(buf,0,sizeof(buf)); while(1){ n=s.server_readn(confd,buf,sizeof(buf)); if(n==boundary.size()&&strcmp(buf,boundary.c_str())==0){ goto exit; } nread+=n; if(buf[n-1]==0){ outStream.write(buf,n-1); }else{ outStream.write(buf,n); } } } readlineCount++; } exit: outStream.close(); s.server_close(confd); return nread; } std::string HttpRequest::getMethod() const{ return method; } std::string HttpRequest::getUrl() const{ return url; } std::string HttpRequest::getHost() const{ return host; } }
Well, the code for uploading the file has also come out. Now let's explain it a little. Before explaining the code, let's take a look at the content sent by the browser to the server when we click the upload file button. For example, I have a text file of test.txt (the file file is used here to view the content. In fact, the binary file is also consistent). The test.txt file contains only one line of the six letters aaabbb. Then you can open the function of Firefox developer network. After clicking send file, you can see the following information on the message header.
These contents have been described in the previous chapters and will not be repeated here. Click the parameter option to see the following information.
Here, lines 1 and 2 are the contents of the request header, followed by an empty line, followed by lines 4-9 of the request body. See that the content of the request body is not directly the content of test.txt. Display '– 23469111452' as the beginning, and this is the separator of the text. The front is fixed with a '-', plus a data automatically generated by the browser. And the explanation of a file is the same, but there are two more '-' after the number. Lines 5 and 6 describe the uploaded file. Then there is a blank line. Line 8 begins with the contents of the file. After knowing the request body, it is easy to write code. The readlineCount variable in the upload above is used for positioning. Look at the line that the server has received. Here is s.server_ The number of lines of readn is not submitted, and the current code segment has been modified, so it is a little different from the blog, and it is basically the same.
After writing here, the file upload and download function of HttpServer has been basically completed. Then you combine these pieces. It will be explained in the next chapter "Http server realizes file upload and download (6)".