Возврат нескольких файлов из действия MVC

Итак, у меня есть приложение MVC 3, в котором есть несколько мест, где текстовый файл генерируется и возвращается в действие, используя:

return File(System.Text.Encoding.UTF8.GetBytes(someString),
                 "text/plain", "Filename.extension");

и это работает сказочно. Теперь у меня есть ситуация, когда я пытаюсь вернуть пару файлов аналогичным образом. В представлении у меня есть ссылка для действия, например "Нажмите здесь, чтобы получить эти 2 файла", и я хотел бы, чтобы оба файла были загружены так же, как один файл загружен в приведенном выше фрагменте кода.

Как я могу это достичь? Очень много искал и даже не видел этого вопроса в любом месте...

Ответ 1

Опираясь на идею Йогендры Сингха и используя DotNetZip:

var outputStream = new MemoryStream();

using (var zip = new ZipFile())
{
    zip.AddEntry("file1.txt", "content1");
    zip.AddEntry("file2.txt", "content2");
    zip.Save(outputStream);
}

outputStream.Position = 0;
return File(outputStream, "application/zip", "filename.zip");

Обновление 2019/04/10: как указывал @Alex, архивирование поддерживается изначально, начиная с .NET Framework 4.5, от JitBit и других:

using (var memoryStream = new MemoryStream())
{
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      var file1 = archive.CreateEntry("file1.txt");
      using (var streamWriter = new StreamWriter(file1.Open()))
      {
         streamWriter.Write("content1");
      }

      var file2 = archive.CreateEntry("file2.txt");
      using (var streamWriter = new StreamWriter(file2.Open()))
      {
         streamWriter.Write("content2");
      }
   }

   return File(memoryStream.ToArray(), "application/zip", "Images.zip")
}

Ответ 2

Я бы посоветовал создать файл zip для включения обоих файлов с помощью шагов (ALGORITHM):

  • Создайте Zip файл и добавьте нужные файлы в zip
  • Верните zip файл, содержащий все необходимые файлы из действия

Синтаксис Java (только для понимания)

      FileOutputStream fos = new FileOutputStream("downloadFile.zip");
      ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
      zos.putNextEntry(new ZipEntry("Filename1.extension"+));
      //write data in FileName1.extension
      zos.write(contentBuffer1, 0, len);

      zos.putNextEntry(new ZipEntry("Filename2.extension"));
      //write data in FileName2.extension
      zos.write(contentBuffer2, 0, len);

      //write other files.....
      zos.close();

После создания файла zip верните вновь созданный файл zip для загрузки.

     return File("downloadFile.zip");

. DOT Net Equivalent с помощью DotNetZip

     var os = new MemoryStream();

     using (var zip = new ZipFile())
     {
         //write the first file into the zip
         zip.AddEntry("file1.txt", "content1");

         //write the second file into the zip
         zip.AddEntry("file2.txt", "content2");

         //write other files.....
         zip.Save(os);
      }

      outputStream.Position = 0;
      return File(outputStream, "application/zip", "filename.zip");

Надеюсь, это поможет!

Ответ 3

Извините, что столкнулся с старым вопросом, но...

Другой альтернативой может быть инициировать несколько загрузок файлов с использованием JavaScript и обслуживать файлы в двух разных методах действий на стороне ASP.NET.

Вы говорите, что у вас есть ссылка:

В представлении у меня есть ссылка действия, например "Нажмите здесь, чтобы получить эти 2 файлы"

Итак, сделайте эту ссылку следующим образом:

<a href="#" onclick="downloadFile(url1); downloadFile(url2);">Click to get 2 files</a>
<script src="download.js"></script>

Я использую download.js script найденный здесь, но вы можете найти множество других других опций, см. этот вопрос SO: запуск загрузки файла с помощью JavaScript, например

Ответ 4

Посмотрите на это SO-решение: MVC Streaming Zip File

Преимущество этого решения заключается в том, что он передает файл клиенту.

Я только что реализовал это решение пару дней назад, и он работал фантастически.