Penjimon Penjimon - 9 days ago 7
HTML Question

C#/MVC - How to loop through Multiple Files (from a file input), when the form contains multiple file inputs?

Here's my HTML:

<input id="openbox_actual" class="btn btn-lg btn-warning" type="file" name="videoFile" style="display: none;" />
<input id="openbox_actual2" class="btn btn-lg btn-warning" type="file" accept="image/*" name="screenShots" multiple="multiple" style="display: none;" />


As shown above, one file input takes a video file, and the other takes multiple image files.

Here's the controller:

HttpPostedFileBase file = Request.Files["videoFile"];
HttpPostedFileBase screens = Request.Files["screenShots"];


From the code above, I can access/upload "file" just fine.

However, I can't figure out how to access all the files inside "screens" ONLY.

I've seen many examples where people iterate through the "HttpPostedFileCollection", but that contains ALL the files, in EVERY file input. I just want all the files from the "screenShots" multiple file input.

Extra points if anyone knows how to "limit" the number of files to 8. (e.g. Where the "screenShots" file input only allows you to upload 8 files total.

Thanks,
You guys are great!

Dai Dai
Answer

You can use GetKey to get the name for a given index.

for( int i = 0 ; i < this.Request.Files.Count; i++ ) {

    String key = this.Request.Files.GetKey( i );

    if( key == "screenShots" ) {
        // do stuff
    }
}

You could do this as a kind of preprocessing step you can re-use elsewhere:

public static Dictionary<String,List<HttpPostedFileBase>> GetFilesAsDictionary( HttpFileCollection files ) {

    Dictionary<String,List<HttpPostedFileBase>> dict = Dictionary<String,List<HttpPostedFileBase>>;

    for( int i = 0 ; i < files.Count; i++ ) {
        String key = file.GetKey( i );

        List<HttpPostedFileBase> list;

        if( !dict.TryGetValue( key, out list ) ) {
            dict.Add( key, list = new List<HttpPostedFileBase>() );
        }

        list.Add( files[i] );
    }

    return dict;
}

Usage:

[HttpPost]
public ActionResult MyAction() {

    Dictionary<String,List<HttpPostedFileBase>> files = UploadUtility.GetFilesAsDictionary( this.Request.Files );

    HttpPostedFileBase video = files["videoFile"][0];
    Int32 screenshotCount = files["screenShots"].Count;
    if( screenshotCount > 8 ) {
        this.ModelState.AddModelError( "", "Limit of 8 screenshots at a time." );
        return this.View( new VideModel() );
    }

    foreach(HttpPostedFileBase screenshot in files["screenShots"]) {
        // do stuff
    }
}