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})