foreach на запит. файли


76

Я намагаюся завантажити кілька файлів у ASP.NET MVC, і у мене є цей простий цикл foreach у моєму контролері

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

Попередній код генерує цю помилку:

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

Я не розумію, чому Request.Files [1] повертає HttpPostedFileBase, але коли він повторюється, повертає рядки (імовірно, імена файлів).

Примітка: Я знаю, що це можна вирішити за допомогою циклу for. Крім того, я спробував використовувати HttpPostedFile, з тією ж помилкою.

Відповіді:


112

Перераховувач HttpFileCollectionповертає ключі (імена) файлів, а не HttpPostedFileBaseоб'єкти. Отримавши ключ, використовуйте властивість Item( []) із ключем (ім’я файлу), щоб отримати HttpPostedFileBaseоб’єкт.

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

    ...
}

1
Чи є спосіб повернути йому HttpPostedFile?
Омар

Не те, що я знаю. Він походить від NameObjectCollectionBase, а перечислювач для цього класу перебирається за ключами.
tvanfosson

Компілятор видає мені помилку і хоче, щоб я використовував HttpPostedFileBaseзамість HttpPostedFile.
Коді,

@tvanfosson у моєму випадку fileName завжди стає "Image", але коли я кажу Request.Files [0]. FileName це дає правильну назву будь-яка ідея? Я використовую MVC5.
Geethanga

1
@Geethanga - "ім'я", яке є ключовим, - це ім'я на вхідному тегу файлу HTML, а не ім'я файлу, який завантажується.
tvanfosson

37

На моїй вкладці HTML:

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

Request.Files матиме дублікат імені в масиві. Тож вам слід вирішити так:

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

Цей метод працював для мене краще, ніж відповідь, оскільки, як зазначає їх html, він дозволяє використовувати кілька файлів в одному файлі.
Caffeinius

4
Це правильна відповідь, оскільки ви повинні мати можливість отримати ім’я файлу за допомогою file.FileName. Якщо ви зробите це з foreachі маєте повторювані імена, перший файл буде збережено кілька разів
Arijoon

13

Ми можемо використовувати LINQ для цього, і все одно використовувати foreach, як запитували:

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

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

Як сказав @tvanfosson, перерахувач повертає імена файлів як рядки, а не як HttpPostedFileBase. Цей метод HttpPostedFileBase this[string name]повертає потрібний нам об’єкт. Якщо це буде HttpFileCollectionBaseреалізовано, IEnumerable<HttpPostedFileBase>ми зможемо нормально робити foreach. Однак він реалізує не загальний IEnumerable.


6

Ви можете спробувати виконати ітерацію рядків і передати їх у HttpPostedFile, замість цього:

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

3
не може неявно перетворити HttpPostedFileBase на HttpPostedFile
Ifeanyi Chukwu

6

На жаль, відповідь tvanfosson для мене не спрацювала. Незважаючи на те, що файли завантажуватимуться чудово, і помилок не виникатиме, виникала б проблема, коли б використовувався лише один із файлів, тому один і той же файл зберігався б двічі, а не використовував би їх обидва.

Здавалося, проблема в операторі foreach, що переглядає імена кожного файлу у файлі Request.Files, чомусь він для мене не працював як ключ, і кожен раз буде вибиратися лише перший файл.

HttpFileCollectionBase files = Request.Files;

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

    ...
}

Це було проблемою для нас на iOS, оскільки функція "сфотографувати" називає кожен файл "image.jpg" - але ця зміна це вирішила. Дякую.
Brian Davis

4

Наступний код працював для мене.

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

0

Ви можете вийти HttpPostedFileз HttpFileCollectionвикористання foreachтаким чином:

foreach (var obj in fileCollection)
{
    HttpPostedFile file = fileCollection.Get(obj.ToString());
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.