I'm attempting upload multiple files in ASP.NET MVC and I have this simple foreach loop in my controller
foreach (HttpPostedFileBase f in Request.Files)
{
if (f.ContentLength > 0)
FileUpload(f);
}
The previous code generates this er开发者_JAVA百科ror:
Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFile'.
What I don't understand is why Request.Files[1] returns an HttpPostedFileBase but when it's iterated over, it returns strings (presumably the file names).
Note: I know this can be solved with a for loop. Also, I tried using HttpPostedFile, with the same error.
The enumerator on the HttpFileCollection
returns the keys (names) of the files, not the HttpPostedFileBase
objects. Once you get the key, use the Item
([]
) property with the key (filename) to get the HttpPostedFileBase
object.
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
...
}
With my tab HTML is:
<input class="valid" id="file" name="file" multiple="" type="file">
Request.Files will have duplicate name in array. So you should solve like this:
for (int i = 0; i < Request.Files.Count; i++ ){
HttpPostedFileBase fileUpload = Request.Files[i];
We can use LINQ to do this and still use foreach as asked:
var files = Enumerable.Range(0, Request.Files.Count)
.Select(i => Request.Files[i]);
foreach (var file in files)
{
// file.FileName
}
As @tvanfosson said, the enumerator returns the file names as strings, not the HttpPostedFileBase
. This method HttpPostedFileBase this[string name]
returns the object we want. If HttpFileCollectionBase
implemented IEnumerable<HttpPostedFileBase>
then we could do the foreach normally. However, it implements a non-generic IEnumerable
.
You might try iterating the strings and casting them to HttpPostedFile instead, like this:
foreach (string file in Request.Files)
{
HttpPostedFile hFile = Request.Files[file] as HttpPostedFile;
if (hFile.ContentLength > 0)
FileUpload(hFile);
}
Unfortunately tvanfosson's answer did not work for me. Although the files would upload just fine, and no error would be thrown, a problem would occur where only one of the files would be used, so the same file would be saved twice rather than using them both.
It seemed to be a problem with the foreach statement looping through the names of each file in the Request.Files, for some reason it wasn't working as a key for me, and only the first file would be selected every time.
HttpFileCollectionBase files = Request.Files;
for(var i = 0; i < files.Count; i++)
{
HttpPostedFileBase file = files[i];
...
}
The following code worked for me.
HttpResponseMessage result = null;
var httpRequest = System.Web.HttpContext.Current.Request;
HttpFileCollection uploadFiles = httpRequest.Files;
var docfiles = new List<string>();
if (httpRequest.Files.Count > 0){
int i;
for (i = 0; i < uploadFiles.Count; i++) {
HttpPostedFile postedFile = uploadFiles[i];
var filePath = @"C:/inetpub/wwwroot/test1/reports/" + postedFile.FileName;
postedFile.SaveAs(filePath);
docfiles.Add(filePath);
}
result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
} else {
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
You can get the HttpPostedFile
out of the HttpFileCollection
using foreach
like this:
foreach (var obj in fileCollection)
{
HttpPostedFile file = fileCollection.Get(obj.ToString());
}
精彩评论