Grant
Grant

Reputation: 11356

c# sharpziplib adding file to existing archive

am trying to add a file to an existing archive using the following code. When run no errors or exceptions are shown but no files are added to the archive either. Any ideas why?

        using (FileStream fileStream = File.Open(archivePath, FileMode.Open, FileAccess.ReadWrite))
        using (ZipOutputStream zipToWrite = new ZipOutputStream(fileStream))
        {
            zipToWrite.SetLevel(9);

            using (FileStream newFileStream = File.OpenRead(sourceFiles[0]))
            {
                byte[] byteBuffer = new byte[newFileStream.Length - 1];

                newFileStream.Read(byteBuffer, 0, byteBuffer.Length);

                ZipEntry entry = new ZipEntry(sourceFiles[0]);
                zipToWrite.PutNextEntry(entry);
                zipToWrite.Write(byteBuffer, 0, byteBuffer.Length);
                zipToWrite.CloseEntry();

                zipToWrite.Close();
                zipToWrite.Finish();
            }
        }

Upvotes: 7

Views: 17940

Answers (8)

bgh
bgh

Reputation: 2160

First of all, use the ZipFile class, as the ZipOutputStream class does not update existing ZIP files.

Second, use the ZipFile constructor that takes the file path as a parameter. This will yield an instance that allows you to manipulate an existing file (don't use the ZipFile.Create() factory method as it will always overwrite any existing ZIP file).

The following code does it:

using var zipFile = new ZipFile(zipFilePath);
zipFile.BeginUpdate();
zipFile.Add(sourceFilePath, Path.GetFileName(sourceFilePath));
zipFile.CommitUpdate();

Upvotes: 0

RvdK
RvdK

Reputation: 19800

From Codeproject someone used this code. Only difference is close and finish otherway around and the write part:

using (ZipOutputStream s = new
ZipOutputStream(File.Create(txtSaveTo.Text + "\\" +
sZipFileName + ".zip")))
{
    s.SetLevel(9); // 0-9, 9 being the highest compression

    byte[] buffer = new byte[4096];

    foreach (string file in filenames)
    {

        ZipEntry entry = new
        ZipEntry(Path.GetFileName(file));

        entry.DateTime = DateTime.Now;
        s.PutNextEntry(entry);

        using (FileStream fs = File.OpenRead(file))
        {
            int sourceBytes;
            do
            {
                sourceBytes = fs.Read(buffer, 0,
                buffer.Length);

               s.Write(buffer, 0, sourceBytes);

            } while (sourceBytes > 0);
        }
    }
    s.Finish();
    s.Close();
}

BTW:

byte[] byteBuffer = new byte[newFileStream.Length - 1];

                newFileStream.Read(byteBuffer, 0, byteBuffer.Length);

This is incorrect, the size is newFileStream.length else the Read goes wrong. You have an array and you make it for example 10-1 is 9 bytes long, from 0 to 8.

But your reading from 0 to 9...

Upvotes: 1

Doug Domeny
Doug Domeny

Reputation: 4470

The ZipOutputStream class does not update existing ZIP files. Use the ZipFile class instead.

Upvotes: 0

Ram Mourya
Ram Mourya

Reputation: 2548

there is a folder ZippedFolder in site's root directory , inside it we have a archive MyZipFiles.

There is a folder with name siteImages which consists of all image files. The following is the code to zip the images

string zipPath = Server.MapPath("~/ZippedFolder/MyZipFiles.zip");
using (ZipFile zip = new ZipFile())
{
 zip.AddFile(Server.MapPath("~/siteImages/img1.jpg"),string.Empty);
 zip.AddFile(Server.MapPath("~/siteImages/img2.jpg"),string.Empty);
 zip.AddFile(Server.MapPath("~/siteImages/img2.jpg"),string.Empty);
 zip.Save(zipPath);
}

if we have different file formats and we want your files to be saved in respective folders,you can specify the code as follows.

string zipPath = Server.MapPath("~/ZippedFolder/MyZipFiles.zip");
using (ZipFile zip = new ZipFile())
{
  zip.AddFile(Server.MapPath("~/siteimages/img1.jpg"), "images");
  zip.AddFile(Server.MapPath("~/siteimages/img2.jpg"), "images");
  zip.AddFile(Server.MapPath("~/documents/customer.pdf"), "files");
  zip.AddFile(Server.MapPath("~/documents/sample.doc"), "files");
  zip.Save(zipPath);
}

now the archive contains two folders images ---- > img1.jpg , img2,.jpg and another folder files --> customer.pdf, sample.doc

Upvotes: 0

Fahar
Fahar

Reputation: 149

I have found a simple solution keeping it to ZipFile and ZipEntry only

        ZipFile zipExisting = ZipFile.Read(Server.MapPath("/_Layouts/includes/Template.zip"));
        ICollection<ZipEntry> entries = _zipFileNew.Entries;
        foreach (ZipEntry zipfile in entries)
        {
            zipExisting.AddEntry(zipfile.FileName, zipfile.InputStream);
        } 

        zipExisting.Save(Response.OutputStream);
        Response.End();

Upvotes: -1

JingvenChina
JingvenChina

Reputation: 9

    /// <summary>
    /// 添加压缩文件 p 为客户端传回来的文件/夹列表,用分号隔开,不包括主路径, zipfile压缩包的名称
    /// </summary>
    /// <param name="p"></param>
    /// <param name="zipfile"></param>
    public void AddZipFile(string p, string zipfile)
    {
        if (ServerDir.LastIndexOf(@"\") != ServerDir.Length - 1)
        {
            ServerDir += @"\";
        }
        string[] tmp = p.Split(new char[] { ';' }); //分离文件列表
        if (zipfile != "") //压缩包名称不为空
        {
            string zipfilepath=ServerDir + zipfile;
            if (_ZipOutputStream == null)
            {
                _ZipOutputStream = new ZipOutputStream(File.Create(zipfilepath));
            }
            for (int i = 0; i < tmp.Length; i++)
            {
                if (tmp[i] != "") //分离出来的文件名不为空
                {
                    this.AddZipEntry(tmp[i], _ZipOutputStream, out _ZipOutputStream); //向压缩文件流加入内容
                }
            }
        }
    }
    private static ZipOutputStream _ZipOutputStream;
    public void Close()
    {
        _ZipOutputStream.Finish();
        _ZipOutputStream.Close();
    }

Upvotes: 0

Cheeso
Cheeso

Reputation: 192577

In DotNetZip, adding files to an existing zip is really simple and reliable.

using (var zip = ZipFile.Read(nameOfExistingZip))
{
    zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
    zip.AddFile(additionalFileToAdd);
    zip.Save();
}

If you want to specify a directory path for that new file, then use a different overload for AddFile().

using (var zip = ZipFile.Read(nameOfExistingZip))
{
    zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
    zip.AddFile(additionalFileToAdd, "directory\\For\\The\\Added\\File");
    zip.Save();
}

If you want to add a set of files, use AddFiles().

using (var zip = ZipFile.Read(nameOfExistingZip))
{
    zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
    zip.AddFiles(listOfFilesToAdd, "directory\\For\\The\\Added\\Files");
    zip.Save();
}

You don't have to worry about Close(), CloseEntry(), CommitUpdate(), Finish() or any of that other gunk.

Upvotes: 15

Vinay Sajip
Vinay Sajip

Reputation: 99445

I think your Finish call should be before your Close call.

Update: This looks like a known bug. It's possible it may already have been fixed - you'll need to check your SharpZipLib version to see if it incorporates any fix. If not, you can work around it by copying all files to a new archive, adding the new file, then moving the new archive to the old archive name.

Upvotes: 1

Related Questions