在对ASP.Net(4.0)Request.Files
(上传)集合进行一些基本验证时,我决定尝试使用LINQ。
该集合为IEnumerable<T>
,因此不提供ForEach。愚蠢地,我决定构建一个可以完成这项工作的扩展方法。对不起,说没那么成功......
运行扩展方法(如下所示)会引发下一个错误:
无法将“System.String”类型的对象强制转换为“System.Web.HttpPostedFile”
显然我没有得到什么,但我看不出它是什么,所以冒着看起来像个白痴的风险(不会是第一次)这里是3个块的代码,还有一个承诺感谢任何帮助。
首先,使用Action参数的扩展方法:
//Extend ForEach to IEnumerated Files
public static IEnumerable<HttpPostedFileWrapper> ForEach<T>(this IEnumerable<HttpPostedFileWrapper> source, Action<HttpPostedFileWrapper> action)
{
//breaks on first 'item' init
foreach (HttpPostedFileWrapper item in source)
action(item);
return source;
}
当内部foreach循环命中'source'中的'item'时,会发生错误。
这是调用代码(变量MaxFileTries和attachPath之前已正确设置):
var files = Request.Files.Cast<HttpPostedFile>()
.Select(file => new HttpPostedFileWrapper(file))
.Where(file => file.ContentLength > 0
&& file.ContentLength <= MaxFileSize
&& file.FileName.Length > 0)
.ForEach<HttpPostedFileWrapper>(f => f.SaveUpload(attachPath, MaxFileTries));
最后,Action目标,保存上传文件 - 我们似乎甚至没有到达这里,但为了以防万一,这里是:
public static HttpPostedFileWrapper SaveUpload(this HttpPostedFileWrapper f, string attachPath, int MaxFileTries)
{
// we can only upload the same file MaxTries times in one session
int tries = 0;
string saveName = f.FileName.Substring(f.FileName.LastIndexOf("\\") + 1); //strip any local
string path = attachPath + saveName;
while (File.Exists(path) && tries <= MaxFileTries)
{
tries++;
path = attachPath + " (" + tries.ToString() + ")" + saveName;
}
if (tries <= MaxFileTries)
{
if (!Directory.Exists(attachPath)) Directory.CreateDirectory(attachPath);
f.SaveAs(path);
}
return f;
}
我承认上面的一些内容是“找到的”一起拼凑起来,所以我很可能得到我应得的东西,但如果有人对此有很好的了解(或者至少已经通过),也许我可以学点东西。
感谢任何人。
答案 0 :(得分:1)
为什么不在原始ToList().ForEach()
上拨打IEnumerable<T>
。
答案 1 :(得分:0)
我认为这就是你想要的
扩展HttpFileCollection
的课程应为
public static class HttpPostedFileExtension
{
//Extend ForEach to IEnumerated Files
public static void ProcessPostedFiles(this HttpFileCollection source, Func<HttpPostedFile, bool> predicate, Action<HttpPostedFile> action)
{
foreach (var item in source.AllKeys)
{
var httpPostedFile = source[item];
if (predicate(httpPostedFile))
action(httpPostedFile);
}
}
}
然后你可以这样使用它:
Request.Files.ProcessPostedFiles(
postedFile =>
{
return (postedFile.ContentLength > 0 && postedFile.FileName.Length > 0);
},
pFile =>
{
//Do something with pFile which is an Instance of HttpPosteFile
});
答案 2 :(得分:0)
首先,编写一个通用的扩展方法:
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (T item in source)
action(item);
return source; // or void, without return
}
然后,Request.Files
可投放到IEnumerable<string>
,而不是IEnumerable<HttpPostedFile>
:
IEnumerable<string> requestFiles = this.Request.Files.Cast<string>();
但确实System.Web.UI.WebControls.FileUpload.PostedFile
是HttpPostedFile
:
HttpPostedFile file = fileUpload.PostedFile;
HttpPostedFileWrapper wrapper = new HttpPostedFileWrapper(file);
但它是单身,而不是集合。从哪里获得你的收藏?
另一种扩展方法:
public static IEnumerable<HttpPostedFile> ToEnumerable(this HttpFileCollection collection)
{
foreach (var item in collection.AllKeys)
{
yield return collection[item];
}
}
用法:
IEnumerable<HttpPostedFile> files = this.Request.Files.ToEnumerable();
IEnumerable<HttpPostedFileWrapper> wrappers = files.Select(f => new HttpPostedFileWrapper(f));