2015-04-15 16 views
10

Czy jest jakoś możliwe utworzenie ZipArchive z pliku (ów) w pamięci (a nie na dysku).Jak stworzyć ZipArchive z plików w pamięci w C#?

Po to przypadek użycia: Wiele plików są odbierane w zmiennej IEnumerable<HttpPostedFileBase>. Chcę spakować wszystkie te pliki razem, używając ZipArchive. Problem polega na tym, że ZipArchive zezwala tylko na CreateEntryFromFile, która oczekuje ścieżki do pliku, gdzie mam tylko pliki w pamięci.

Pytanie: Czy istnieje sposób, aby użyć „strumień”, aby utworzyć „wejście” w ZipArchive, tak, że można bezpośrednio umieścić w treści pliku w zip?

Nie chcę najpierw zapisywać plików, tworzyć zip (ze ścieżek zapisanych plików), a następnie usuwać pojedyncze pliki.

Tutaj attachmentFiles jest IEnumerable<HttpPostedFileBase>

using (var ms = new MemoryStream()) 
{ 
    using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true)) 
    { 
     foreach (var attachment in attachmentFiles) 
     { 
      zipArchive.CreateEntryFromFile(Path.GetFullPath(attachment.FileName), Path.GetFileName(attachment.FileName), 
           CompressionLevel.Fastest); 
     } 
    } 
    ... 
} 
+3

Czy próbowałeś to http://stackoverflow.com/questions/12347775/ziparchive- tworzy-invalid-zip-file/12350106 # 12350106? –

+0

Dlaczego nie utworzyć pliku tymczasowego, a następnie zwolnić po zakończeniu archiwum? – RussDunn

+0

Chcę uniknąć tworzenia pliku tymczasowego i usunąć go, jeśli to możliwe. To właśnie napisałem w pytaniu, ale jeśli nie ma innego sposobu, będę musiał to zrobić. – Flair

Odpowiedz

14

Tak, można to zrobić, stosując metodę ZipArchive.CreateEntry, jak @AngeloReis zauważył w komentarzach, a opisane here na nieco inny problem.

Twój kod będzie wyglądać następująco:

using (var ms = new MemoryStream()) 
{ 
    using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true)) 
    { 
     foreach (var attachment in attachmentFiles) 
     { 
      var entry = zipArchive.CreateEntry(attachment.FileName, CompressionLevel.Fastest); 
      using (var entryStream = entry.Open()) 
      { 
       attachment.InputStream.CopyTo(entryStream); 
      } 
     } 
    } 
    ... 
} 
+2

Pracowałem jak czar, dzięki! Użyłem go do stworzenia pliku zip z plików PDF, które zapisałem jako bajtowe [] w bazie danych. Nie trzeba w ogóle angażować systemu plików. Użytkownik klika przycisk, a plik .zip jest pobierany za pośrednictwem przeglądarki internetowej. (BTW, w najbardziej wewnętrznym "użyciu" bloku I zamiast tego użyłem entryStream.Write (arrBytes, 0, arrBytes.Length); – ClearCloud8

+1

Co to jest attachmentFiles? – Demodave

0

Po pierwsze dzięki @Alex idealnego odpowiedź.
również dla scenariusza trzeba czytać z systemów plików:

using (var ms = new MemoryStream()) 
{ 
    using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true)) 
    { 
     foreach (var file in filesAddress) 
     { 
      zipArchive.CreateEntryFromFile(file, Path.GetFileName(file)); 
     } 
    } 

    ... 
} 

za pomocą System.IO.Compression.ZipFileExtensions