2016-06-15 4 views
2

geworfen Ich habe eine URL, die eine ZIP-Datei enthält. Die Dateien müssen aus der URL entpackt werden. Die URL wird mit webclient geöffnet und gelesen und dann zu einem Stream hinzugefügt. Es wird dann im ZipArchive-Objekt verwendet, das die Dateien entpackt und auf dem Laufwerk D: \ speichert. Wenn eine Datei etwa 400 MB groß ist, bekomme ich die 'System.OutOfMemoryException'.'System.OutOfMemoryException' wurde in ZipArchive für große Datei von URL

Stream muss verwendet werden, da der WebClient.OpenRead (Uri-Adresse) einen Stream zurückgibt. Sowie die Verwendung von ZipArchive (Stream-Stream).

enter image description here

Wie kann ich verhindern, diese Nachricht von zu bekommen?

string zipFileUrl = "https://www.dropbox.com/s/clersbjdcshpdy6/oversize_zip_test_0.zip?dl=0" 
string output_path = @"D:\"; 

using (WebClient webClient = new WebClient()) 
{ 

    using (Stream streamFile = webClient.OpenRead(zipFileUrl)) 
    { 
      using (ZipArchive archive = new ZipArchive(streamFile))//ERROR HERE 
      {         
       var entries = archive.Entries; 
       //Loops thru each file in Zip and adds it to directory 
       foreach (var entry in entries) 
       { 
       if (entry.FullName != "/" && entry.Name != "") 
       { 

        string completeFileName = Path.Combine(output_path, entry.FullName); 
        string directory = Path.GetDirectoryName(completeFileName); 

        //If directory does not exist then we create it. 
        if (!Directory.Exists(directory)) 
        { 
         Directory.CreateDirectory(directory); 
        } 
        //Extracts zip from URL to extract path, and overwrites if file exists. 
        entry.ExtractToFile(completeFileName, true);               
       } 
      } 
     } 
    } 
+0

Ich bin sehr überrascht, Sie erhalten den Fehler auf 'OpenRead', Öffnen des Streams zum Lesen sollte nicht so viel Speicher aufnehmen. –

+0

Was ist der StackTrace? –

+0

Kein Fehler wie dieser an meinem Ende, obwohl ich 'End of Central Directory Datensatz konnte nicht gefunden werden 'in der nächsten Zeile. – DavidG

Antwort

4

Ich denke here might be your problem, von der ZipArchive.Init Methode

private void Init(Stream stream, ZipArchiveMode mode, Boolean leaveOpen) 
{ 
    Stream extraTempStream = null; 

    try 
    { 
     _backingStream = null; 

     //check stream against mode 
     switch (mode) 
     { 
      case ZipArchiveMode.Create: 
       // (SNIP) 
      case ZipArchiveMode.Read: 
       if (!stream.CanRead) 
        throw new ArgumentException(SR.ReadModeCapabilities); 
       if (!stream.CanSeek) 
       { 
        _backingStream = stream; 
        extraTempStream = stream = new MemoryStream(); 
        _backingStream.CopyTo(stream); 
        stream.Seek(0, SeekOrigin.Begin); 
       } 
       break; 
      case ZipArchiveMode.Update: 
       // (SNIP) 
      default: 
       // (SNIP) 
     } 
    // (SNIP) 
} 

wenn streamFile.CanSeek falsch ist (was von einem WebClient wird es sein) kopiert es die gesamte Datei in den Speicher dann auf die Datei funktioniert. Dies verbraucht den gesamten Speicher.

Versuchen Sie, eine 3rd-Party-Bibliothek zu finden, die Zip-Dateien verarbeitet und keinen Stream benötigt, der Suchen unterstützt. Wenn Sie nicht können, kopieren Sie zuerst die Datei auf den Datenträger in den temporären Ordner mit einem FileStream mit der FileOptions.DeleteOnClose Option übergeben, dann verwenden Sie diesen Stream in Ihrer Zip, bevor Sie den Stream schließen.

string zipFileUrl = "https://www.dropbox.com/s/clersbjdcshpdy6/oversize_zip_test_0.zip?dl=0"; 
string output_path = @"D:\"; 

using (var tempFileStream = new FileStream(Path.GetTempFileName(), FileMode.Create, 
              FileAccess.ReadWrite, FileShare.None, 
              4096, FileOptions.DeleteOnClose)) 
{ 
    using (WebClient webClient = new WebClient()) 
    { 
     using (Stream streamFile = webClient.OpenRead(zipFileUrl)) 
     { 
      streamFile.CopyTo(tempFileStream); 
     } 
    } 
    tempFileStream.Position = 0; 
    using (ZipArchive archive = new ZipArchive(tempFileStream)) 
    { 
     var entries = archive.Entries; 
     //Loops thru each file in Zip and adds it to directory 
     foreach (var entry in entries) 
     { 
      if (entry.FullName != "/" && entry.Name != "") 
      { 

       string completeFileName = Path.Combine(output_path, entry.FullName); 
       string directory = Path.GetDirectoryName(completeFileName); 

       //If directory does not exist then we create it. 
       if (!Directory.Exists(directory)) 
       { 
        Directory.CreateDirectory(directory); 
       } 
       //Extracts zip from URL to extract path, and overwrites if file exists. 
       entry.ExtractToFile(completeFileName, true); 
      } 
     } 
    } 
} 
+0

Kopieren der Datei an den Speicherort zuerst und dann entpacken arbeitete große Scott Ich sollte darüber zuerst nachdenken. Danke für die Hilfe. – Apollo

Verwandte Themen