简体   繁体   English

使用DotNetZip库从内存流创建zip文件时如何传递文件夹层次结构

[英]How to pass folder hierarchy when creating zip file from memory stream using DotNetZip library

Requirement: 1) creating split zips file in multiple segments(say size - 1 GB/500 MB), so that they can be downloaded through browser. 要求:1)在多个段中创建分割的zip文件(例如大小-1 GB / 500 MB),以便可以通过浏览器下载它们。 The total zip volume of all the segments could exceed 10 GB 2) the zip content could be multiple files or a folder containing sub folders and files 3) the content of the file are read from Cloud in the form of stream. 所有段的总zip量可能超过10 GB 2)zip内容可以是多个文件或包含子文件夹和文件的文件夹3)以流的形式从Cloud读取文件的内容。 The meta information for the files(like folder hierarchy) are locally available 文件的元信息(如文件夹层次结构)在本地可用

I am using DotNetZip library to achieve the task. 我正在使用DotNetZip库来完成任务。 The code is as following: 代码如下:

long length = default(long);
            Stream fileReadStream;

            long Space = default(long);
            string tempZipFile = string.Empty;
            FileZipStatus oldStatue = new FileZipStatus();
            byte[] Buffer = new byte[1024 * 1024];

            if (zipFileName != null && !zipFileName.ToUpper().EndsWith(".ZIP")) zipFileName += ".zip";
            string strTempFolder = "";
            using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
            {
                try
                {
                    strTempFolderPath = tempZipOutPutFilePath + "\\";
                    string strTempFolderName = DateTime.Now.Ticks.ToString();
                    strTempFolder = strTempFolderPath + strTempFolderName;
                    if (userFileList.Count > 0)
                    {
                        if (Directory.Exists(strTempFolder))
                        {
                            Directory.Delete(strTempFolder);
                        }
                        Directory.CreateDirectory(strTempFolder);
                    }
                    foreach (UserFile userFile in userFileList)
                    {
                        WebResponse response = null;
                        try
                        {
                            WebRequest request = null;
                            IDictionary<string, object> _dictionary = new Dictionary<string, object>();
                            /// First 
                            FileSystemEnum fileSysEnum = FileSystemBase.GetFileSystemEnumByStorageId(userFile.StorageId);
                            IFileSystemLib ifileSystemLocal = FileSystemFactory.GetSpecificInstance(fileSysEnum);

                            fileReadStream = ifileSystemLocal.GetFile(userFile.FilePath, userFile.GuidName, ref request, ref response, _dictionary);
                            long filesize = default(long);

                            long.TryParse(ifileSystemLocal.GetFileContentLength(userFile.FilePath, userFile.GuidName).ToString(), out filesize);
                            Space = (Space > default(long)) ? (Space + filesize) : filesize;
                            //Now we have to store the data, so that we must access the file

                            int dataToRead;
                            FileStream writeStream = new FileStream(strTempFolder + "\\" + userFile.FileName, FileMode.Create, FileAccess.Write);
                            while ((dataToRead = fileReadStream.Read(Buffer, 0, Buffer.Length)) > 0)
                            {
                                writeStream.Write(Buffer, 0, dataToRead);
                            }
                            writeStream.Close();

                            zip.AddFile(strTempFolder + "\\" + userFile.FileName, userFile.RelativePath);
                            fileReadStream.Close();                            
                        }
                        catch (Exception ex)
                        {
                            LogManager.Trace(ex, "ZIpping Block - ZIPFileName", zipFileName + "File to zip" + userFile.GuidName);
                        }
                        finally
                        {
                            if (response != null) response.Close();
                        }
                    }
                }
                catch (Exception ex)
                {
                    _currentStatus = FileZipStatus.NotAvailable;
                    oldStatue = UpdateZipStatus(ObjectZipID, Space, FileZipStatus.Failed);
                    throw ex;
                }
                finally
                {   
                }
                try
                {
                    zip.Comment = "This zip was created at " + System.DateTime.Now.ToString("G");
                    zip.MaxOutputSegmentSize = 200 * 1024 * 1024;   // 200 mb
                    zip.Save(strTempFolderPath + "\\" + zipFileName);
                    oldStatue = UpdateZipStatus(ObjectZipID, Space, FileZipStatus.Available);
                    length = new FileInfo(strTempFolderPath + "\\" + zipFileName).Length;
                    _currentStatus = FileZipStatus.Available;
                    // deleting temp folder
                    Directory.Delete(strTempFolder, true);
                }
                catch (Exception ex)
                {
                    _currentStatus = FileZipStatus.NotAvailable;
                    oldStatue = UpdateZipStatus(ObjectZipID, Space, FileZipStatus.Failed);
                    length = default(long);
                    throw ex;
                }
            }

There are a limitation of the DotNetZip libray used in the above code. 上面的代码中使用的DotNetZip libray有一个限制 It either needs a) files saved on disk as input. 它要么需要a)作为输入保存在磁盘上的文件。 In that case folder hierarchy information could be passed for each file. 在这种情况下,可以为每个文件传递文件夹层次结构信息。 or 2) if stream is passed as input, folder hierarchy information could NOT be passed for file. 或2)如果将流作为输入传递,则无法为文件传递文件夹层次结构信息。

I need to pass in the folder hierarchy information for each file as well as read the input from stream. 我需要传递每个文件的文件夹层次结构信息以及从流中读取输入。 As the zip content could be huge(could exceed 10 GB), do not want to save the files on temporary storage in web server. 由于zip内容可能很大(可能超过10 GB),因此不想将文件保存在Web服务器的临时存储中。 Can Anyone help like how to pass folder hierarchy when creating zip file? 在创建zip文件时,有人可以帮忙喜欢如何传递文件夹层次结构吗? thanks 谢谢

i got the solution. 我得到了解决方案。 here is the code 这是代码

private void button2_Click(object sender, EventArgs e)
        {
            using (SqlConnection sqlConn = new SqlConnection(@"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
            {
                string query = String.Format(@"SELECT [FilePath],[FileName],[FileData] FROM [TestTable]");
                SqlCommand cmd = new SqlCommand(query, sqlConn);
                cmd.Connection.Open();

                System.IO.MemoryStream memStream = null;
                ZipFile zip = new ZipFile();
                zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
                // the above line would split zip file into multiple files and each file
                //size would be 1MB
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        byte[] data = (byte[])reader["FileData"];
                        memStream = new System.IO.MemoryStream(data);
                        string strFile = reader["FilePath"].ToString() + "\\" + reader["FileName"].ToString();
                        ZipEntry ze = zip.AddEntry(strFile, memStream);
                    }
                }
                zip.Save(@"e:\MyCustomZip.zip");
                memStream.Dispose();
                MessageBox.Show("Job Done");
                // here u can save the zip in memory stream also there is a overload insteaa of saving in HD
            }
        }

this approach stores the zip content in memory. 这种方法将zip内容存储在内存中。 Hence, when the zip content is huge, say exceeds 5 GB then then it crashes. 因此,当zip内容很大时,比如说超过5 GB,则会崩溃。 Need to write to fileOutputStream mapped to physical file 需要写入fileOutputStream映射到物理文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM