2009-11-19 5 views
53

Je tente télécharger plusieurs fichiers dans ASP.NET MVC et moi avons cette simple boucle foreach dans mon contrôleurforeach sur Request.Files

foreach (HttpPostedFileBase f in Request.Files) 
{ 
    if (f.ContentLength > 0) 
     FileUpload(f); 
} 

Le code précédent génère cette erreur:

Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFile'. 

Ce que je ne comprends pas, c'est pourquoi Request.Files [1] retourne un HttpPostedFileBase mais quand il est répété, il retourne des chaînes (probablement les noms de fichiers).

Remarque: Je sais que cela peut être résolu avec une boucle for. En outre, j'ai essayé d'utiliser HttpPostedFile, avec la même erreur.

Répondre

85

Le recenseur sur les HttpFileCollection retourne les clés (noms) des fichiers, et non les objets HttpPostedFileBase. Une fois que vous obtenez la clé, utilisez la propriété Item ([]) avec la clé (nom de fichier) pour obtenir l'objet HttpPostedFileBase.

foreach (string fileName in Request.Files) 
{ 
    HttpPostedFileBase file = Request.Files[fileName]; 

    ... 
} 
+1

Y at-il un moyen de le faire renvoyer un fichier HttpPostedFile à la place? – Omar

+0

Pas que je sache. Il dérive de NameObjectCollectionBase et l'énumérateur de cette classe parcourt les clés. – tvanfosson

+0

Le compilateur me lance une erreur et veut que j'utilise 'HttpPostedFileBase' au lieu de' HttpPostedFile'. – Cody

5

Vous pouvez essayer itérer les cordes et les jetant à la place HttpPostedFile, comme ceci:

foreach (string file in Request.Files) 
    { 
     HttpPostedFile hFile = Request.Files[file] as HttpPostedFile; 
     if (hFile.ContentLength > 0) 
      FileUpload(hFile); 
    } 
+2

ne peut pas implicitement convertir HttpPostedFileBase à HttpPostedFile –

3

Malheureusement, la réponse de tvanfosson n'a pas fonctionné pour moi. Bien que les fichiers soient bien téléchargés et qu'aucune erreur ne soit générée, un problème surviendrait lorsqu'un seul des fichiers serait utilisé, donc le même fichier serait sauvegardé deux fois plutôt que de les utiliser tous les deux.

Il semblait y avoir un problème avec l'instruction foreach bouclant les noms de chaque fichier dans Request.Files, pour une raison quelconque, il ne fonctionnait pas comme une clé pour moi, et seul le premier fichier serait sélectionné chaque temps.

HttpFileCollectionBase files = Request.Files; 

for(var i = 0; i < files.Count; i++) 
{ 
    HttpPostedFileBase file = files[i]; 

    ... 
} 
21

Avec mon onglet HTML est:

<input class="valid" id="file" name="file" multiple="" type="file"> 

Request.Files auront nom en double dans le tableau. Donc, vous devriez résoudre comme ceci:

for (int i = 0; i < Request.Files.Count; i++){ 
    HttpPostedFileBase fileUpload = Request.Files[i]; 
+0

Celui-ci fonctionnait mieux pour moi que la réponse parce que, comme le souligne leur HTML, il permet plusieurs fichiers dans la même entrée de fichier. – Caffeinius

+2

C'est la réponse correcte car vous devriez pouvoir obtenir le nom de fichier avec 'file.FileName'. Si vous le faites avec 'foreach' et que vous avez des noms en double, le premier fichier sera sauvegardé plusieurs fois – Arijoon

4

Le code suivant a fonctionné pour moi.

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; 
} 
10

Nous pouvons utiliser LINQ pour le faire et toujours utiliser foreach comme demandé:

var files = Enumerable.Range(0, Request.Files.Count) 
    .Select(i => Request.Files[i]); 

foreach (var file in files) 
{ 
    // file.FileName 
} 

Comme @tvanfosson dit, le recenseur retourne les noms de fichiers sous forme de chaînes, pas les HttpPostedFileBase. Cette méthode HttpPostedFileBase this[string name] renvoie l'objet que nous voulons. Si HttpFileCollectionBase implémenté IEnumerable<HttpPostedFileBase> alors nous pourrions faire le foreach normalement. Cependant, il implémente un IEnumerable non générique.