c++使用poco上传form表单(可从磁盘和内存中加载文件),解析form表单

1、上传比较简单,已经有封装好的类Poco::Net::StringPartSource可以使用;该类可以添加一般的text字段,也可以添加文件字段。

如下

#include 
#include 
#include 
#include 
#include "Poco/Net/HTMLForm.h"
#include "Poco/StreamCopier.h"
#include "Poco/FileStream.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/PartSource.h"
#include "Poco/Net/StringPartSource.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPClientSession.h"

int main()
{
    std::ostringstream out_str;
    Poco::FileInputStream i_str("test.png");
    Poco::StreamCopier::copyStream(i_str, out_str);
    std::cout << "file size: " << out_str.str().size() << std::endl;

    Poco::Net::HTMLForm form_data(Poco::Net::HTMLForm::ENCODING_MULTIPART);
    form_data.set("valu1", "200,300,300,100"); 普通字段,默认是text/plain
    form_data.set("valu2", "23.898");
    form_data.addPart("feature", new Poco::Net::StringPartSource("{id: 1, personId: 2}", "application/json"));//除了text/plain类型的,其它非file字段
    form_data.addPart("file", new Poco::Net::StringPartSource(out_str.str(), "application/octet-stream", "scne.jpg")); //从内存中加载
    //form_data.addPart("file", new Poco::Net::StringPartSource("/home/whl/Picture/test.png"));从磁盘中加载

    Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/rest/api/v1/sync/syncFaceSnap", Poco::Net::HTTPMessage::HTTP_1_1);
    Poco::Net::HTTPClientSession *httpSession = new Poco::Net::HTTPClientSession("localhost", 17077);
    form_data.prepareSubmit(request);
    request.set("uuid", "1233"); //添加http头
    form_data.write(httpSession->sendRequest(request));

    Poco::Net::HTTPResponse res;
    std::istream &is = httpSession->receiveResponse(res);
    Poco::StreamCopier::copyStream(is, std::cout);
    return 0;
}

          还可以自己实现Poco::Net::PartSource

2、解析的话要麻烦一些

  先要写好一个解析的handler,我的如下,可以解析多个文件

namespace Poco{
    namespace Net{
        class StringPartHandler: public PartHandler
        {
        public:
            StringPartHandler()
            {
            }

            void handlePart(const MessageHeader& header, std::istream& stream)
            {
                std::string disp = header["Content-Disposition"];
                disp = disp.substr(disp.find_first_of(';') + 1);
                std::vector infoVec = DataSyncServer::StringSplit(disp, ";");
                std::map disp_map;
                for(std::string &disp_str : infoVec)
                {
                    int pos = disp_str.find_first_of('=');
                    std::string key = disp_str.substr(0, pos);
                    key.erase(std::remove(key.begin(),key.end(), ' '), key.end());
                    key.erase(std::remove(key.begin(),key.end(), '"'), key.end());

                    std::string value = disp_str.substr(pos + 1);
                    value.erase(std::remove(value.begin(),value.end(), ' '), value.end());
                    value.erase(std::remove(value.begin(),value.end(), '"'), value.end());
                    disp_map[key] = value;
                }
                auto ilter = disp_map.find("name");
                if(ilter == disp_map.end()){
                    return;
                }
                std::string name = ilter->second;

                ilter = disp_map.find("filename");
                if(ilter == disp_map.end()){
                    return;
                }
                std::string filename = ilter->second;

                std::ostringstream  ostr;
                Poco::StreamCopier::copyStream(stream, ostr);
                part_map_.insert(std::make_pair(name, std::make_pair(filename, ostr.str())));
            }

            bool HasFiled(const std::string &name){
                return part_map_.find(name) != part_map_.end();
            }

            const std::pair& FileData(const std::string &name) const{
                auto ilter = part_map_.find(name);
                if(ilter != part_map_.end()){
                    return ilter->second;
                }

                return std::pair();
            }

            const std::map>& PartMap() const{
                return part_map_;
            }

        private:
            std::map> part_map_;
        };
    }
}

然后,将请求和body内容做为参数构造form

            Poco::Net::HTTPRequest request("POST", "/rest/api/upload");
            request.setContentType("content-type: multipart/form-data; boundary="MIME_boundary_15952AD9169A8FE6");
            Poco::Net::StringPartHandler sah;
            std::istringstream istr(content);
            Poco::Net::HTMLForm form(request, istr, sah);

            Poco::Net::NameValueCollection::ConstIterator ilter = form.find("userId");
            std::cout << "userId" << ilter->second << std::endl;
            std::string file_data = sah.FileData("file").second;
            std::string file_name = sah.FileData("file").firts;

      cmakelist中如下配置

find_package(Poco REQUIRED Util Net)
target_link_libraries(${PROJECT_NAME} ${Poco_LIBRARIES})

 

你可能感兴趣的:(c++,服务器)