cppcms读取multipart/form-data

 前段时间研究了一下怎样通过cppcms框架读取multipart/form-data类型的请求,由于网上资料较少,只能花了一些时间阅读源代码,了解了基本的使用方法,写个小例子测试一下。

该例子中涉及到的请求数据包括:一般的string、浮点型数组、图像数据,其中,浮点型数组也是以字符串形式传输,图像数据则是以文件形式传输。字符串传输的数组数据,需要还原成原始的浮点型数组,本例中是自己写的字符串解析函数实现,也可以通过其他方式实现,比如转成JSON格式等。

/* 定义一个服务类,用于接收和处理HTTP请求。该服务会接收/formdata这个字段并进行请求的内容解析和处理。 */
class TestCppCms: public cppcms::application {
public:
    TestCppCms(cppcms::service &srv) :
        cppcms::application(srv)
    {
        std::cout<<"constructor"<<std::endl;

		/* Test for multi-part data request */
		dispatcher().assign("/formdata", &TestCppCms::receive_form_data, this);
        mapper().assign("formdata", "/formdata");

        mapper().root("/");
    }

    /* 接收数据 */
	/* Test for receive form data */
	void receive_form_data()
	{
		/* 输出接收到的请求的请求方法,即POST、GET或者其他方法等 */
        std::cout << "request_method: " << request().request_method() << std::endl;
		/* 输出请求内容的类型 */
        std::cout << "content_type: " << request().content_type() << std::endl;
        /* 输出请求内容的长度 */
		std::cout << "content_length: " << request().content_length() << std::endl;
		
		/* Get post data in this request */
		std::string task_id, service_name, points_str;
		std::string key_value_str;
		/* 获取key为task_id的value值 */
		task_id = request().post("task_id");
		std::cout << "task_id = " <<  task_id << std::endl;
		
        /* 获取service_name对应的value值 */
		service_name = request().post("service_name");
		std::cout << "service_name = " <<  service_name << std::endl;
		
        /* 读取points对应的value值,读取到的是一个包含多个浮点坐标的字符串,需要后续解析成实际的浮点数 */
		points_str = request().post("points");
		std::cout << "points_str: " << points_str << std::endl;
		
        /* 对读取到的浮点数组字符串进行解析,输出数组 */		
        std::vector<std::string> points_str_vec = parse_array_from_string(points_str, "[,] ");
		std::vector<double> points_array;
		std::cout << "Points array: " << points_str_vec.size() << " elements." << std::endl;
		for(int i = 0; i < points_str_vec.size(); i++)
		{
			float f = stof(points_str_vec[i]);
			points_array.push_back(f);
			std::cout << f << " ";
		}
		std::cout << std::endl;
		
		/* 读取请求中的文件数据 */
        /* Get uploaded file in this request */
		std::vector<booster::shared_ptr<cppcms::http::file> > files = request().files();
		for(int i = 0; i < files.size(); i++)
		{
			booster::shared_ptr<cppcms::http::file> file_tmp;
			file_tmp = files[i];
			
			/* Get file name */
			std::string file_name = file_tmp->name();    //files[i]->name;
			std::cout << "File " << i << " name: " << file_name << std::endl;
			
            /* 将文件数据读入字符串向量 */
			/* Get file data and save file */
			file_tmp->data().seekg(0);
            std::string img_data = gulp(file_tmp->data());
			std::vector<char>vec(img_data.begin(), img_data.end());

            /* 从字符串向量中解析出图像文件数据 */
            std::cout<<"img_data_size = " << img_data.size() << std::endl;
            cv::Mat mat = cv::imdecode(vec, CV_LOAD_IMAGE_COLOR);
			char img_name[50];
			sprintf(img_name, "recv_%d.jpg", i+1);
            cv::imwrite(img_name, mat);
		}
		
	    /* 向请求端返回响应信息 */
		response().out() << "Received images num: " << files.size() << "\n"
			<< "task_id = " << task_id << "\n"
			<< "service_name = " << service_name << "\n";
		
	}
   
    std::string gulp(std::istream &in)
    {
        std::string str;
        char buffer[4096];
        while (in.read(buffer, sizeof(buffer)))
            str.append(buffer, sizeof(buffer));
        str.append(buffer, in.gcount());
        return str;
    }
    
};

其中,以上调用的从字符串解析出浮点数组的函数定义如下,输入参数包含一个输入字符串in_str,和一个分隔符字符串delim,分隔符可包含多种,按任意顺序放入字符串即可。

/* Split string and parse array information */
std::vector<std::string> parse_array_from_string(std::string in_str, const std::string &delim)
{
	std::vector<std::string> sub_str_vec;
	size_t pos = 0, pos_start = 0, pos_end = 0;
	size_t len;
	
	while(pos < in_str.length())
	{
		pos_start = in_str.find_first_not_of(delim, pos);
		std::cout << "pos_start = " << pos_start << std::endl;
		
		if(pos_start != std::string::npos)
		{
			pos_end = in_str.find_first_of(delim, pos_start + 1);
			std::cout << "pos_end = " << pos_end << std::endl;
			
			if(pos_end != std::string::npos)
			{
				len = pos_end - pos_start;   // sub-string lenght
			}
			else   // No delim pattern found
			{
				len = in_str.length() - pos_start;   // sub-string lenght
			}
			 
			std::string sub_str = in_str.substr(pos_start, len);
			sub_str_vec.push_back(sub_str);
			
			pos = pos_start + len + 1;
		}
		else
		{
			std::cout << "Hit end of the input string. pos = " << pos << std::endl;
			break;
		}
	}
	
	return sub_str_vec;

}

让我们来测试一下:

int main(int argc, char **argv)
{

	/* 读取当前服务的配置文件 */
	/* Read config file */
	std::ifstream file("config.js");
    cppcms::json::value settings;
    settings.load(file, true);
	
    /* 启动服务 */
    try 
	{
        cppcms::service app(settings);
        app.applications_pool().mount(cppcms::applications_factory<TestCppCms>());
        app.run();
    }
    catch(std::exception const &e) 
	{
        std::cerr<<e.what()<<std::endl;
    }
}

功能OK。由于原来的实验环境处于非工作状态,暂时无法贴结果,等环境恢复后再补充吧。

附上postman请求截图:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用WebClient发送HTTP请求时,可以使用multipart/form-data编码来上传文件或者发送表单数据。multipart/form-data编码是一种在HTTP传输中常用的编码方式,它可以将多个不同类型的数据(如文本、二进制文件等)一起传输到服务器。以下是一个使用WebClient发送multipart/form-data请求的示例代码: ``` using System.Net; WebClient client = new WebClient(); string url = "http://example.com/upload"; string filePath = @"C:\example.jpg"; // 设置请求头部信息 client.Headers["Content-Type"] = "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"; // 构造表单数据 string formData = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"example.jpg\"\r\n" + "Content-Type: image/jpeg\r\n\r\n"; // 读取文件数据 byte[] fileData = File.ReadAllBytes(filePath); // 构造请求体 string requestContent = formData + Encoding.UTF8.GetString(fileData) + "\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--\r\n"; // 发送请求并获取响应 byte[] responseBytes = client.UploadData(url, "POST", Encoding.UTF8.GetBytes(requestContent)); string responseString = Encoding.UTF8.GetString(responseBytes); ``` 在以上示例中,请求头部信息中指定了使用multipart/form-data编码,并设置了boundary参数。接着构造了一个表单数据,其中包括了一个文件和一个文本字段。文件数据通过读取文件内容得到,并与表单数据一起构造了请求体。最后通过调用WebClient的UploadData方法发送请求,并获取服务器的响应。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值