【发布时间】:2014-02-18 23:55:44
【问题描述】:
我为我的问题找到了一些解决方案,这很简单: 我有一个字符串,看起来像这样:
"\r\nContent-Disposition: form-data; name=\"ctl00$cphMainContent$grid$ctl03$ucPicture$ctl00\""
我的目标是分解它,所以我有一个值字典,例如: 键=“名称”,值? “ctl...”
我的方法是:用“\r\n”分割,然后用等号或冒号分割。 这很好用,但后来一些有趣的测试人员上传了一个包含所有允许字符的文件,这使得字符串看起来像这样:
"\r\nContent-Disposition: form-data; name=\"ctl00_cphMainContent_grid_ctl03_ucPicture_btnUpload$fileUpload\"; filename=\"C:\\Users\\matthias.mueller\\Desktop\\- ie+![]{}_-´;,.$¨@#ç %&()=~^`'.jpg\"\r\nContent-Type: image/jpeg"
当然,简单的拆分不再起作用,因为它现在拆分了文件名。 我通过读出“filename=”并转义我要拆分的符号来纠正这个问题,然后创建一个正则表达式。
现在我的问题来了:我找到了两个正则表达式样本,它们可以处理等号、分号和冒号。一个是:
[^\\]=
我找到的另一个是:
(?<!\\\\)=
问题是,第一个不只是拆分,而是拆分等号和这个符号之前的一个字符,这意味着我在字典中的键是“nam”而不是“name”
第二个在这个问题上工作正常,但它仍然拆分文件名中的转义等号。
我解决这个问题的方法是否有效?会有更好的解决方案吗?为什么第一个正则表达式会删减一个字符?
编辑:为避免混淆,我的转义字符串如下所示: “内容处置:表单数据;名称=\”ctl00_cphMainContent_grid_ctl03_ucPicture_btnUpload$fileUpload\”;文件名=\”C\:\Users\matthias.mueller\Desktop\-ie+![]{}_-´\;,.$ ¨@#ç %&()\=~^`'.jpg\""
所以我基本上想要:除转义的以外,用等号分割。顺便说一句:这里的字符串只显示了一个\,但是有2个。
编辑 2:好的,我似乎有一个可行的解决方案,但它太丑了:
Dictionary<string, string> ParseHeader(byte[] bytes, int pos)
{
Dictionary<string, string> items;
string header;
string[] headerLines;
int start;
int end;
string input = _encoding.GetString(bytes, pos, bytes.Length - pos);
start = input.IndexOf("\r\n", 0);
if (start < 0) return null;
end = input.IndexOf("\r\n\r\n", start);
if (end < 0) return null;
WriteBytes(false, bytes, pos, end + 4 - 0); // Write the header to the form content
header = input.Substring(start, end - start);
items = new Dictionary<string, string>();
headerLines = Regex.Split(header, "\r\n");
Regex regLineParts = new Regex(@"(?<!\\\\);");
Regex regColon = new Regex(@"(?<!\\\\):");
Regex regEqualSign = new Regex(@"(?<!\\\\)=");
foreach (string hl in headerLines)
{
string workString = hl;
//Escape the Semicolon in filename
if (hl.Contains("filename"))
{
String orig = hl.Substring(hl.IndexOf("filename=\"") + 10);
orig = orig.Substring(0, orig.IndexOf('"'));
string toReplace = orig;
toReplace = toReplace.Replace(toReplace, toReplace.Replace(";", @"\\;"));
toReplace = toReplace.Replace(toReplace, toReplace.Replace(":", @"\\:"));
toReplace = toReplace.Replace(toReplace, toReplace.Replace("=", @"\\="));
workString = hl.Replace(orig, toReplace);
}
string[] lineParts = regLineParts.Split(workString);
for (int i = 0; i < lineParts.Length; i++)
{
string[] p;
if (i == 0)
p = regColon.Split(lineParts[i]);
else
p = regEqualSign.Split(lineParts[i]);
if (p.Length == 2)
{
string orig = p[0];
orig = orig.Replace(@"\\;", ";");
orig = orig.Replace(@"\\:", ":");
orig = orig.Replace(@"\\=", "=");
p[0] = orig;
orig = p[1];
orig = orig.Replace(@"\\;", ";");
orig = orig.Replace(@"\\:", ":");
orig = orig.Replace(@"\\=", "=");
p[1] = orig;
items.Add(p[0].Trim(), p[1].Trim());
}
}
}
return items;
}
需要进一步测试。
【问题讨论】:
-
“文件名中的转义等号”在哪里?我没看到。
-
你不能为此使用一些 mime/email/http 标头解析器吗?
-
请注意,“\”不包含反斜杠,只有一个
"。 -
ContentDispositionHeaderValue.Parse