使用 DotNetZip 库从内存流创建 zip 文件时如何传递文件夹层次结构
How to pass folder hierarchy when creating zip file from memory stream using DotNetZip library
要求:
1) 在多个段中创建拆分 zips 文件(比如大小 - 1 GB/500 MB),以便可以通过浏览器下载它们。所有段的总 zip 体积可能超过 10 GB
2) zip 内容可以是多个文件或包含子文件夹和文件的文件夹
3)文件内容以流的形式从云端读取。文件的元信息(如文件夹层次结构)在本地可用
我正在使用 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 库存在限制。
它要么需要
a) 作为输入保存在磁盘上的文件。在那种情况下,可以为每个文件传递文件夹层次结构信息。
要么
2) 如果流作为输入传递,则无法为文件传递文件夹层次结构信息。
我需要传递每个文件的文件夹层次信息以及从流中读取输入。由于 zip 内容可能很大(可能超过 10 GB),
不想将文件保存在 Web 服务器的临时存储中。任何人都可以帮助创建 zip 文件时如何传递文件夹层次结构吗?谢谢
我得到了解决方案。这是代码
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
}
}
此方法将 zip 内容存储在内存中。因此,当 zip 内容很大时,比如超过 5 GB,然后它就会崩溃。需要写入映射到物理文件的fileOutputStream
要求: 1) 在多个段中创建拆分 zips 文件(比如大小 - 1 GB/500 MB),以便可以通过浏览器下载它们。所有段的总 zip 体积可能超过 10 GB 2) zip 内容可以是多个文件或包含子文件夹和文件的文件夹 3)文件内容以流的形式从云端读取。文件的元信息(如文件夹层次结构)在本地可用
我正在使用 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 库存在限制。 它要么需要 a) 作为输入保存在磁盘上的文件。在那种情况下,可以为每个文件传递文件夹层次结构信息。 要么 2) 如果流作为输入传递,则无法为文件传递文件夹层次结构信息。
我需要传递每个文件的文件夹层次信息以及从流中读取输入。由于 zip 内容可能很大(可能超过 10 GB), 不想将文件保存在 Web 服务器的临时存储中。任何人都可以帮助创建 zip 文件时如何传递文件夹层次结构吗?谢谢
我得到了解决方案。这是代码
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
}
}
此方法将 zip 内容存储在内存中。因此,当 zip 内容很大时,比如超过 5 GB,然后它就会崩溃。需要写入映射到物理文件的fileOutputStream