最近一个winform项目想直接用http协议与java端进行双向通讯,发现HttpListener可以实现http通讯,如果提交form的enctype=application/x-www-form-urlencoded则可以通过HttpUtility.ParseQueryString来解析HttpListenerRequest.InputStream中的内容,但如果是multipart/form-data,没有找到可以直接解析的类。
在网上找了半天,发现了http://www.xuebuyuan.com/464241.html,可以实现解析上传文件,不过处理一个1M的上传表单,竟然要8秒,性能实在无法接受(后来发现瓶颈主要在流读取和数组读取的速度差异)。
想着dotnet内部肯定有实现类,在用reflection反复查找后,终于确定HttpMultipartContentTemplateParser是可以用来解析MFC1867协议的,但由于是内部类无法在外部实现,故将代码整理如下。
/*
RFC1867协议 举例
------WebKitFormBoundaryKcbJOyftlttL1JBB
Content-Disposition: form-data; name="name"
zq
------WebKitFormBoundaryKcbJOyftlttL1JBB
Content-Disposition: form-data; name="myfile"; filename="IMG_20130219_181308.jpg"
Content-Type: image/jpeg
[二进制数据]
------WebKitFormBoundaryKcbJOyftlttL1JBB--
*/
/// <summary>
/// 解析RFC1867协议
/// </summary>
public class HttpMultipartFormParser {
private string boundary;
private byte[] _boundary;
private byte[] _data;
private int _length;
private int _lineLength = -1;
private int _lineStart = -1;
private int _pos;
private bool _lastBoundaryFound;
private string _partContentType;
private int _partDataLength = -1;
private int _partDataStart = -1;
private string _partFilename;
private string _partName;
private Encoding _encoding;
public HttpMultipartFormParser(HttpListenerRequest request, Encoding encoding) {
this._encoding = encoding;
//Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Regex regex = new Regex("boundary=(.*)$");
Match match = regex.Match(request.ContentType);
if (match.Success) {
boundary = match.Groups[1].Value;
_boundary = _encoding.GetBytes("--" + boundary);
}
Stream input = request.InputStream;
//将上传文件保存到内存
BufferedStream br = new BufferedStream(input);
MemoryStream ms = new MemoryStream();