使用cURL向.NET MultipartFileStreamProvider上传文件报错问题
解决MultipartFileStreamProvider处理带引号文件名报错的问题
这个问题的根源在于.NET的MultipartFileStreamProvider默认实现没有正确遵循RFC 6266中关于Content-Disposition头里quoted-string格式文件名的解析规则——它直接把包含引号的文件名字符串传给了Path.GetFileName,而引号属于路径中的非法字符,因此抛出了Illegal characters in path异常。
解决方案:自定义StreamProvider解析带引号的文件名
我们可以通过继承MultipartFormDataStreamProvider并重写GetLocalFileName方法,手动处理带引号的文件名,确保解析后的文件名符合系统路径规则。
以下是完整的自定义实现代码:
public class RfcCompliantMultipartStreamProvider : MultipartFormDataStreamProvider { public RfcCompliantMultipartStreamProvider(string rootPath) : base(rootPath) { } public override string GetLocalFileName(HttpContentHeaders headers) { // 获取默认的文件名(此时可能包含首尾引号) var rawFileName = base.GetLocalFileName(headers); if (string.IsNullOrWhiteSpace(rawFileName)) { // 处理空文件名的情况,返回默认值或者抛出异常,根据你的需求调整 return base.GetLocalFileName(headers); } // 解析quoted-string格式的文件名:去掉首尾引号,同时转义还原内部的引号 if (rawFileName.StartsWith("\"") && rawFileName.EndsWith("\"")) { rawFileName = rawFileName.Substring(1, rawFileName.Length - 2) .Replace("\\\"", "\""); } // 确保只返回文件名部分,避免路径遍历攻击 return Path.GetFileName(rawFileName); } }
代码说明
- 解析引号包裹的文件名:检查文件名是否以引号开头和结尾,如果是,去掉首尾的引号,并将转义的引号(
\")还原为普通引号,这符合RFC中quoted-string的转义规则。 - 安全处理:最后调用
Path.GetFileName确保只提取文件名部分,防止恶意用户通过构造特殊文件名进行路径遍历攻击。 - 兼容性:这个实现既符合RFC 6266的标准,又解决了curl请求中带引号文件名的问题,同时保留了原StreamProvider的其他功能。
使用方式
在你的.NET应用中,替换原来使用CustomMultipartFormDataStreamProvider的地方,改用这个自定义的RfcCompliantMultipartStreamProvider即可:
var provider = new RfcCompliantMultipartStreamProvider(yourUploadPath); await Request.Content.ReadAsMultipartAsync(provider); // 后续处理上传的文件...
这样修改后,curl发送的带引号文件名的请求就能被正确处理,不会再抛出非法字符的异常了。
内容的提问来源于stack exchange,提问作者wrschneider
相关产品推荐
相关产品推荐

