c++使用poco上傳form表單(可從磁盤和內存中加載文件),解析form表單

1、上傳比較簡單,已經有封裝好的類Poco::Net::StringPartSource可以使用;該類可以添加一般的text字段,也可以添加文件字段。

如下

#include <iostream>
#include <fstream>
#include <sstream>
#include <memory>
#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<std::string> infoVec = DataSyncServer::StringSplit(disp, ";");
                std::map<std::string,std::string> 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<std::string, std::string>& FileData(const std::string &name) const{
                auto ilter = part_map_.find(name);
                if(ilter != part_map_.end()){
                    return ilter->second;
                }

                return std::pair<std::string, std::string>();
            }

            const std::map<std::string, std::pair<std::string, std::string>>& PartMap() const{
                return part_map_;
            }

        private:
            std::map<std::string, std::pair<std::string, std::string>> 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})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章