背景
使用boost.beast
实现简单的HTTP服务,但是boost.beast
没有提供对表单数据的解析,为此需要自己实现解析表单数据。
application/x-www-form-urlencoded
的格式与URL的查询字符串格式一样,只是会被URL编码,比较容易处理
但multipart/form-data
相对而言比较复杂
multipart/form-data
multipart/form-data
主要是为了解决application/x-www-form-urlencoded
编码格式在传输大量二进制数据或包含非ASCII字符文本时的低效问题。multipart/form-data
的数据由多个part组成,part间通过boundary分隔符进行分割,每个part由header和content组成
multipart/form-data
的格式大致为:
----------------------------904587217962624105581666
Content-Disposition: form-data; name=“projectName”testProject
----------------------------904587217962624105581666
Content-Disposition: form-data; name=“clientName”aaa
-----------------------------904587217962624105581666–
发送multipart/form-data
的Http请求头中的Content-Type
信息:
multipart/form-data; boundary=----------------------------904587217962624105581666
更多的关于multipart/form-data
信息可以查看Returning Values from Forms: multipart/form-data
FormItem
使用FormItem
来表示multipart/form-data
中的一个part,FormItem
并不复制数据内容,只保存指向表单数据的指针,并通过保存记录本部分数据在表单数据中的起始位置_dataStart
和数据长度_dataLength
来表示数据,避免拷贝造成的开销。
除了数据内容外,还需要保存每部分内容的头部信息,包括name
,contentType
,fileName
class FormItem{
/**
* 将MultipartContentElement作为MultipartContentParse的友元类
* 使得MultipartContentParse对MultipartContentElement具有完的控制权
* 因为两个类是强相关的,且MultipartContentElement中的数据应由
* MultipartContentParse进行设置
*/
friend class FormDataParser;
private:
std::string _fileName; ///< 表单元为文件时,具有文件名
std::string _name; ///< 表单元的key
std::string _contentType; ///< 表单元该部分的类型
const std::shared_ptr<std::string> _content; ///< 指request中的表单内容
int _dataStart; ///< 属于本单元素的内容的起始下标
int _dataLength; ///< 属于本单元素的内容的长度
/**
* MultipartContentElement对象只能由MultipartContentPars生成
* 将构造函数的访问权设置为private,防止外部创建
* @param name 表单元素的名
* @param fileName 文件时fileName不为空
* @param contentType 类型
* @param content 指向表单数据的指针
* @param start 本表单元素的起始位置
* @param length 本表单元素的数据长度
* @return MultipartContentElement对象
*/