2015-04-06 67 views
0

要求: 1)創建多段(比如大小爲1 GB/500 MB)的分割zip文件,以便可以通過瀏覽器下載。所有分段的總壓縮量可能超過10 GB 2)壓縮內容可能是多個文件或包含子文件夾和文件的文件夾 3)文件的內容以流的形式從雲中讀取。文件的元信息(如文件夾層次結構)在本地可用如何在使用DotNetZip庫從內存流創建zip文件時傳遞文件夾層次結構

我正在使用DotNetZip庫來實現此任務。該代碼是如下:

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; 
       } 
      } 

有在上面的代碼中使用的DotNetZip libray的限制。它需要 a)保存在磁盤上的文件作爲輸入。在這種情況下,可以爲每個文件傳遞文件夾層次結構信息。 或 2)如果流作爲輸入傳遞,文件夾層次結構信息不能傳遞給文件。

我需要傳遞每個文件的文件夾層次結構信息以及從流中讀取輸入。由於zip內容可能很大(可能超過10 GB),因此 不希望將文件保存在Web服務器的臨時存儲中。任何人都可以幫助像創建zip文件時如何傳遞文件夾層次結構?謝謝

回答

0

我得到了解決方案。這裏是代碼

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 
      } 
     } 
-1

這種方法將zip內容存儲在內存中。因此,當郵件內容很大時,比方說超過5 GB,那麼它就會崩潰。需要寫入fileOutputStream映射到物理文件

+0

可以討論如何寫入fileOutputStream映射到具有提示和示例代碼位的物理文件。謝謝 – Mou 2015-04-17 19:36:27

相關問題