2015-04-27 2 views
2

Я создал текстовый файл в папке и заархивировал эту папку и сохранил местоположение @same для целей тестирования. Я хотел загрузить этот zip-файл непосредственно на пользовательский компьютер после его создания. Я использую библиотеку dotnetzip и сделать следующее:Загрузка zip-файла через ASP.NET MVC с использованием DotNetZip

Response.Clear(); 
Response.ContentType = "application/zip"; 
Response.AddHeader("content-disposition", "filename=" + "sample.zip"); 
using (ZipFile zip = new ZipFile()) 
{ 
    zip.AddDirectory(Server.MapPath("~/Directories/hello")); 
    zip.Save(Server.MapPath("~/Directories/hello/sample.zip")); 
} 

Может кто-то пожалуйста, подсказывает, как почтовый файл может быть загружен в конце пользователя.?

+0

возможно дубликат [ASP MVC Скачать Zip Files] (http://stackoverflow.com/questions/15385958/asp-mvc-download-zip-files) –

ответ

12

Вы можете использовать File метод контроллера возвращать файл, например:

public ActionResult Download() 
{ 
    using (ZipFile zip = new ZipFile()) 
    { 
     zip.AddDirectory(Server.MapPath("~/Directories/hello")); 
     zip.Save(Server.MapPath("~/Directories/hello/sample.zip")); 
     return File(Server.MapPath("~/Directories/hello/sample.zip"), 
            "application/zip", "sample.zip"); 
    } 
} 

Если почтовый файл не требуется в противном случае должны быть сохранены, нет необходимости писать его в файл на сервере:

public ActionResult Download() 
{ 
    using (ZipFile zip = new ZipFile()) 
    { 
     zip.AddDirectory(Server.MapPath("~/Directories/hello")); 

     MemoryStream output = new MemoryStream(); 
     zip.Save(output); 
     return File(output, "application/zip", "sample.zip"); 
    } 
} 
+0

Получение ошибки в дубликате заголовки, полученные с сервера. У меня нет запятой в имени моего файла, но он все еще не работает. В Response.AddHeader() может возникнуть проблема. Ответьте @CMate – user2801336

+0

@ user2801336: вы не должны добавлять заголовки вручную с помощью Response.AddHeader(), так как он будет автоматически добавлен методом File. Я специально исключил ручное добавление заголовка. – mcserep

+0

Спасибо, Бадди. Это сработало для меня. – user2801336

0

Создать GET -Только действие контроллера, который возвращает FileResult, как это:

[HttpGet] 
public FileResult Download() 
{ 
    // Create file on disk 
    using (ZipFile zip = new ZipFile()) 
    { 
     zip.AddDirectory(Server.MapPath("~/Directories/hello")); 
     //zip.Save(Response.OutputStream); 
     zip.Save(Server.MapPath("~/Directories/hello/sample.zip")); 
    } 

    // Read bytes from disk 
    byte[] fileBytes = System.IO.File.ReadAllBytes(
     Server.MapPath("~/Directories/hello/sample.zip")); 
    string fileName = "sample.zip"; 

    // Return bytes as stream for download 
    return File(fileBytes, "application/zip", fileName); 
} 
4

Прежде всего, рассмотрите способ без создания каких-либо файлов на диске сервера. Плохая практика. Я бы рекомендовал создать файл и закрепить его в памяти. Надеюсь, вы найдете мой пример ниже полезным.

/// <summary> 
///  Zip a file stream 
/// </summary> 
/// <param name="originalFileStream"> MemoryStream with original file </param> 
/// <param name="fileName"> Name of the file in the ZIP container </param> 
/// <returns> Return byte array of zipped file </returns> 
private byte[] GetZippedFiles(MemoryStream originalFileStream, string fileName) 
{ 
    using (MemoryStream zipStream = new MemoryStream()) 
    { 
     using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) 
     { 
      var zipEntry = zip.CreateEntry(fileName); 
      using (var writer = new StreamWriter(zipEntry.Open())) 
      { 
       originalFileStream.WriteTo(writer.BaseStream); 
      } 
      return zipStream.ToArray(); 
     } 
    } 
} 

/// <summary> 
///  Download zipped file 
/// </summary> 
[HttpGet] 
public FileContentResult Download() 
{ 
    var zippedFile = GetZippedFiles(/* your stream of original file */, "hello"); 
    return File(zippedFile, // We could use just Stream, but the compiler gets a warning: "ObjectDisposedException: Cannot access a closed Stream" then. 
       "application/zip", 
       "sample.zip"); 
} 

Примечания к выше коде:

  1. Передача MemoryStream экземпляр требует проверки, что она открыта, действует и т.д. Я опустил их. Я предпочел бы передать байтовый массив содержимого файла вместо экземпляра MemoryStream, чтобы сделать код более надежным, но для этого примера это было бы слишком много.
  2. Он не показывает, как создать требуемый контекст (ваш файл) в памяти. Я хотел бы обратиться к классу MemoryStream.
+0

С файлом в памяти можно приостановить загрузку в браузере? –

+0

Вы можете, но возобновление загрузки вызовет все действия в методе Download (создание потоков, файл zipping и т. Д.). Подробнее см. Здесь http://superuser.com/a/641957. Конечно, сохранение кэшированного файла для загрузки уменьшит накладные расходы для сервера, но вам придется обрабатывать одновременный доступ нескольких пользователей к одному и тому же ресурсу/странице и, вероятно, здесь вы столкнетесь с проблемами. –

0

Для тех, кто просто хочет вернуть существующий файл Zip из папки App_Data (просто свалка в ваших почтовых файлов там), в главном контроллере создать этот метод действия:

public FileResult DownLoad(string filename) 
    { 
     var content = XFile.GetFile(filename); 
     return File(content, System.Net.Mime.MediaTypeNames.Application.Zip, filename); 

    } 

Get File является метод продление:

public static byte[] GetFile(string name) 
    { 
     string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); 
     string filenanme = path + "/" + name; 
     byte[] bytes = File.ReadAllBytes(filenanme); 
     return bytes; 
    } 

Главная Индексный контроллер выглядит следующим образом:

@model List<FileInfo> 

<table class="table"> 
    <tr> 
     <th> 
      @Html.DisplayName("File Name") 
     </th> 
     <th> 
      @Html.DisplayName("Last Write Time") 
     </th> 
     <th> 
      @Html.DisplayName("Length (mb)") 
     </th> 
     <th></th> 
    </tr> 

    @foreach (var item in Model) 
    { 
     <tr> 
      <td> 
       @Html.ActionLink("DownLoad","DownLoad",new {filename=item.Name}) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Name) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.LastWriteTime) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Length) 
      </td> 
     </tr> 
    } 
</table> 

Основной метод действия индексного файла:

public ActionResult Index() 
    { 
     var names = XFile.GetFileInformation(); 
     return View(names); 
    } 

Где GetFileInformation является метод расширения:

public static List<FileInfo> GetFileInformation() 
    { 
     string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); 
     var dirInfo = new DirectoryInfo(path); 
     return dirInfo.EnumerateFiles().ToList(); 
    } 
2

просто исправление для решения Клауса: (так как я не могу добавить комментарий, я должен добавить еще ответ!)

Решение отличное, но для меня он дал поврежденный zip-файл, и я понял, что это из-за возврата перед завершением zip-объекта, поэтому он не закрыл ZIP и не повредил почтовый индекс.

поэтому для исправления нам нужно просто переместить обратную линию после использования zip-блока, чтобы он работал. конечный результат:

/// <summary> 
///  Zip a file stream 
/// </summary> 
/// <param name="originalFileStream"> MemoryStream with original file </param> 
/// <param name="fileName"> Name of the file in the ZIP container </param> 
/// <returns> Return byte array of zipped file </returns> 
private byte[] GetZippedFiles(MemoryStream originalFileStream, string fileName) 
{ 
    using (MemoryStream zipStream = new MemoryStream()) 
    { 
     using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) 
     { 
      var zipEntry = zip.CreateEntry(fileName); 
      using (var writer = new StreamWriter(zipEntry.Open())) 
      { 
       originalFileStream.WriteTo(writer.BaseStream); 
      } 
     } 
     return zipStream.ToArray(); 
    } 
} 

/// <summary> 
///  Download zipped file 
/// </summary> 
[HttpGet] 
public FileContentResult Download() 
{ 
    var zippedFile = GetZippedFiles(/* your stream of original file */, "hello"); 
    return File(zippedFile, // We could use just Stream, but the compiler gets a warning: "ObjectDisposedException: Cannot access a closed Stream" then. 
       "application/zip", 
       "sample.zip"); 
} 
Смежные вопросы