-->

Extracting zip from stream with DotNetZip

2019-08-13 02:26发布

问题:

public void ZipExtract(Stream inputStream, string outputDirectory)
    {

        using (ZipFile zip = ZipFile.Read(inputStream))
        {
            Directory.CreateDirectory(outputDirectory);
            zip.ExtractSelectedEntries("name=*.jpg,*.jpeg,*.png,*.gif,*.bmp", " ", outputDirectory,
                                       ExtractExistingFileAction.OverwriteSilently);
        }
    }
 [HttpPost]
    public ContentResult Uploadify(HttpPostedFileBase filedata)
    {
        var path = Server.MapPath(@"~/Files");
        var filePath = Path.Combine(path, filedata.FileName);
       if (filedata.FileName.EndsWith(".zip"))
        {

            ZipExtract(Request.InputStream,path);

        }
        filedata.SaveAs(filePath); 

            _db.Photos.Add(new Photo
                               {
                                   Filename = filedata.FileName
                               });

        _db.SaveChanges();
        return new ContentResult{Content = "1"};

    }

I try to read zip archive from stream and extract files. Got the following exception in the line "using (ZipFile zip = ZipFile.Read(inputStream))" : ZipEntry::ReadDirEntry(): Bad signature (0xC618F879) at position 0x0000EE19 Any ideas how to handle this exception?

回答1:

The error is occurring because the stream you are trying to read is not a valid zip bytestream. In most cases, Request.InputStream will not represent a zip file. It will represent an HTTP message, which will look like this:

POST /path/for/your/app.aspx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; ...)
Content-Type: application/x-www-form-urlencoded
Content-Length: 11132

 ...more stuff here...

I think what you are doing is trying to read that message as if it were a zip file. That's not gonna work. The file content is actually embedded in the "... more stuff here..." part.

To work toward solving this, I suggest you work in smaller steps.

First, get the file upload to work, saving the content of the uploaded file to a filesystem file on the server. Then, on the server, try to open the file as a zipfile. If it works, then you should be able to replace the file saving portion, with ZipFile.Read(). If you cannot open the file that you saved, then it means that the file that you saved is not a zip file. Either it is incomplete, or, more likely, it includes extraneous data, like the HTTP headers.

If you have trouble successfully uploading a binary file like a zip file, first work on uploading a text file. You can more easily verify the upload of a text file on the server, by simply opening the uploaded content in a text editor, and checking that it contains exactly the content of the file that was uploaded from the client. Once you have this working, move to a binary file. Then you can move to a full streaming approach, using DotNetZip to read the stream. Once you get to this point, there should be no need to save the file to the filesystem, before reading it as a zip file, but you may want to save it anyway, for other reasons.

To help, you may want to use Fiddler2, the debugging HTTP proxy. Install it on the browser machine, turn it on, and it will help you see the messages that get sent from the browser to the ASPNET application on the server. You'll see that a file upload contains more that just the bare file data.



回答2:

A more stable solution could be to use ICSharpCode ZipLib: http://www.sharpdevelop.net/OpenSource/SharpZipLib/Default.aspx