squid-box / SevenZipSharp

Fork of SevenZipSharp on CodePlex
GNU Lesser General Public License v3.0
274 stars 101 forks source link

I have an exception in SevenZipExtractor.BeginExtractArchive(string directory) when unpacking a stream #25

Open altbodhi opened 6 years ago

altbodhi commented 6 years ago
       var zipStream = new FileStream("c:\\backup\\file.zip", FileMode.Open);
            SevenZip.SevenZipBase.SetLibraryPath("x86\\7z.dll");
            var z = new SevenZip.SevenZipExtractor(zipStream, "pass");
                 z.BeginExtractArchive("c:\\tmp\\test_ext");

.net 4.5.2

The specified stream can not seek or read. Имя параметра: stream

Server stack trace: в SevenZip.SevenZipExtractor.ValidateStream(Stream stream) в C:\projects\SevenZipSharp\SevenZip\SevenZipExtractor.cs:строка 691 в SevenZip.SevenZipExtractor.Init(Stream stream) в C:\projects\SevenZipSharp\SevenZip\SevenZipExtractor.cs:строка 100 в SevenZip.SevenZipExtractor.RecreateInstanceIfNeeded() в C:\projects\SevenZipSharp\SevenZip\SevenZipExtractorAsynchronous.cs:строка 36 в SevenZip.SevenZipExtractor.DisposedCheck() в C:\projects\SevenZipSharp\SevenZip\SevenZipExtractor.cs:строка 352 в SevenZip.SevenZipExtractor.ExtractArchive(String directory) в C:\projects\SevenZipSharp\SevenZip\SevenZipExtractor.cs:строка 1270

squid-box commented 6 years ago

I'm unable to reproduce the error, but your code snippet also seems incomplete - if you're calling BeginExtractArchive you'll need to ensure it's finished before continuing.

The error you're getting, as it states occurs because the stream returns false on either CanSeek or CanRead - both of which are needed to extract files from it. A common cause for these to be false is if the stream is already closed.

I'd check if the file you're trying to use is available to you and that the FileStream is still open. Also which version of 7z.dll are you using?

altbodhi commented 6 years ago

7z.dll x86 version 9.22

ср, 26 сент. 2018 г., 17:35 Joel Ahlgren notifications@github.com:

I'm unable to reproduce the error, but your code snippet also seems incomplete - if you're calling BeginExtractArchive you'll need to ensure it's finished before continuing.

The error you're getting, as it states occurs because the stream returns false on either CanSeek or CanRead - both of which are needed to extract files from it. A common cause for these to be false is if the stream is already closed.

I'd check if the file you're trying to use is available to you and that the FileStream is still open. Also which version of 7z.dll are you using?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/squid-box/SevenZipSharp/issues/25#issuecomment-424667935, or mute the thread https://github.com/notifications/unsubscribe-auth/AXOMwSFinm3Dvo-st9vItC9YE3CEoxUEks5ue1iJgaJpZM4W59wF .

squid-box commented 6 years ago

7z 9.22 is almost 7.5 years old, I'd try with 18.05 (which is the only one I'll attempt to support, until a newer version is released).

I'd also suggest using something like this:

using (var zipStream = new FileStream(@"c:\backup\file.zip", FileMode.Open))
{
    using (var z = new SevenZipExtractor(zipStream, "pass"))
    {
        z.ExtractArchive(@"c:\tmp\test_ext");
    }
}

Unless you're actually handling the asynchronous part outside of your snippet.

altbodhi commented 6 years ago

I have tried 7z 18.5 but still i have same error. Yes, of course, i will do it with sync method.

Full code:

            var done = false;
            void Extract()
            {

            var zipStream = new FileStream("c:\\backup\\001_documents.zip", FileMode.Open);
            SevenZip.SevenZipBase.SetLibraryPath("7z.dll");
            var z = new SevenZip.SevenZipExtractor(zipStream, "123");
            z.ArchiveFileNames.ForEach(Console.WriteLine);
             z.ExtractionFinished += (sender, eventArgs) => { done = true; };
             z.BeginExtractArchive("c:\\tmp\\test_ext");
            }

            Extract();
            while (!done)
            {
                Thread.Sleep(1000);
                Application.DoEvents();
            }

            Console.WriteLine("done");
squid-box commented 6 years ago

It looks like there's an actual problem with doing asynchronous extraction from a stream (it seems the archive is never extracted), I'll look into it in a while.

In your case, is there a reason you're manually opening a FileStream instead of just passing the file to BeginExtractArchive?

In your code above, change var z = new SevenZip.SevenZipExtractor(zipStream, "123"); to var z = new SevenZip.SevenZipExtractor("c:\\backup\\001_documents.zip", "123"); and remove the zipStream variable. This seems to work for me at least.

altbodhi commented 6 years ago

Thank you. Yes, We use SevenSharp as part archive utils for a lot of various operations in applications(not only files). I look at code:

        private void RecreateInstanceIfNeeded()
        {
            if (NeedsToBeRecreated)
            {
                NeedsToBeRecreated = false;
                Stream backupStream = null;
                string backupFileName = null;
                if (String.IsNullOrEmpty(_fileName))
                {
                    backupStream = _inStream;
                }
                else
                {
                    backupFileName = _fileName;
                }
                **CommonDispose(); // here dispose and null _inStream, but backupStream not null !!!**
                if (backupStream == null)
                {
                    Init(backupFileName);
                }
                else
                {
                    Init(backupStream);
                }
            }
        }

I think that it is point where there is a mistake.

kjbtech commented 2 years ago

Same trouble below (attachment is MimePart, from MimeKit library) :

MemoryStream memoryStream = new();
await attachment.Content.DecodeToAsync(memoryStream, cancellationToken);
memoryStream.Seek(0, SeekOrigin.Begin);

if (Path.GetExtension(attachment.ContentType.Name) == ".7z")
{
    SevenZipBase.SetLibraryPath(@"X\7z.dll");
    using (SevenZipExtractor sevenZipExtractor = new(memoryStream))
    {
        for (var i = 0; i < sevenZipExtractor.ArchiveFileData.Count; i++)
        {
            using (MemoryStream memoryStreamForPdf = new())
            {
                ArchiveFileInfo fileInArchive = sevenZipExtractor.ArchiveFileData[i];

                if (MimeTypes.GetMimeType(fileInArchive.FileName) == KnownMimeTypes.Pdf)
                {
                    sevenZipExtractor.ExtractFile(sevenZipExtractor.ArchiveFileData[i].Index, memoryStreamForPdf);

                    // internal process
                }
            }
        }
    }
}