如何按RFC2231规范解析带分段参数的HTTP请求头?
问题
需要按照RFC2231规范解析带分段参数的HTTP请求头,比如下面这个请求头:
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; name*0*=US-ASCII''%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81%20%D0%BF%D1%80%D0; name*1*=%B5%D0%B4%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%BD%D0; name*2*=%B0%20%D0%B7%D0%B0%D0%BA%D1%83%D0%BF%D0%BA%D1%83%20#Z_226.xlsx
用以下C#代码解析时:
var ct = new ContentType(headerValueText); var name = ct.Name;
name返回null,实际和name相关的参数都存在Parameters集合里,键为["name*0*", "name*1*", "name*2*"]。请问该如何正确解析并解码这个name值?
我当前的实现方式如下:
var namesColection = new List<(int position, string value)>(); foreach (DictionaryEntry parametr in ct.Parameters) { if (parametr.Key.ToString().Contains("name")) { var position = parametr.Key.ToString().Split('*')[1]; namesColection.Add((int.Parse(position), parametr.Value.ToString())); } } var nameString = string.Join("", namesColection.OrderBy(p => p.position)); var decodingName = HttpUtility.UrlDecode(nameString.ToString().Split('\'')[2], Encoding.UTF8);
解决方案
你的思路方向是对的,但可以优化细节来适配RFC2231规范,同时处理更多边界情况:
- 精准匹配分段参数键:不要只用
Contains("name"),应该匹配^name\*\d+\*$的格式,避免误匹配其他带name的参数 - 正确解析RFC2231的值格式:每个分段值的格式是
[charset]''[encoded-part],其中charset可以省略(默认US-ASCII),所以要正确提取编码部分 - 统一解码逻辑:确保使用正确的编码(可从参数中提取charset,而非硬编码UTF8)
优化后的代码示例:
using System.Text.RegularExpressions; // 收集所有符合规则的name分段参数 var nameSegments = new List<(int Index, string EncodedPart)>(); var segmentPattern = new Regex(@"^name\*(\d+)\*$"); foreach (DictionaryEntry param in ct.Parameters) { var key = param.Key.ToString(); var match = segmentPattern.Match(key); if (match.Success) { int index = int.Parse(match.Groups[1].Value); var valueParts = param.Value.ToString().Split('\''); // 提取编码部分:若有三段则取第三段,两段则说明省略了charset取第二段 string encodedPart = valueParts.Length >=3 ? valueParts[2] : valueParts[1]; nameSegments.Add((index, encodedPart)); } } // 按索引排序后拼接所有编码片段 var combinedEncoded = string.Join("", nameSegments.OrderBy(s => s.Index)); // 解码:可从第一个有效分段的valueParts[0]获取charset,这里默认用UTF8示例 var decodedName = HttpUtility.UrlDecode(combinedEncoded, Encoding.UTF8);
关键说明:
- 正则匹配参数键:用
^name\*(\d+)\*$确保只匹配name*N*格式的参数,避免误判 - 值格式处理:RFC2231允许值的格式为
charset''encoded或直接encoded(省略charset),所以要判断拆分后的数组长度 - 编码适配:如果需要严格遵循规范,可以从第一个分段的
valueParts[0]获取charset,再对应选择编码类型解码
内容的提问来源于stack exchange,提问作者GeorgiyEihler
相关产品推荐
相关产品推荐

