今天项目有一新需求,需要从数据库中将文件打包,在客户端(BS架构)下载。由于系统将所有上传的文件都存储在数据库,这就牵涉到两点,首先要把数据库中的数据读出来,然后再利用ICSharpCode将文件打包。
由于是BS架构,因而不可能将数据库中的文件存储为某个临时文件,再进行打包,所以只好把文件以MemoryStream形式写入到Zip包中,同时需要注意的是,ZipEntry是不好重复的,如果碰到相同的文件名,是需要加以区分的,比如aaa.jpg,aaa(1).jpg,aaa(2).jpg。
在写入Zip包前,还需要用CRC来格式化buffer,就像是写到磁盘一样。
最后通过Response.OutputStream来实现客户端下载Zip文件。还有就是别忘记把Stream关闭。
下面这段代码就是实现了这样的需求。
#region Initialize
MemoryStream ziparchive = new MemoryStream();
ZipOutputStream MyZipStream = new ZipOutputStream(ziparchive);
// This is required inorder to close the zip archive and leave the stream intact
MyZipStream.IsStreamOwner = false;
// Set the compression level
MyZipStream.SetLevel(6);
bool? IsDefault = null;
bool? IsThumbnail = null;
if (ConvertClass.BooleanWrapper(rbtDownloadOptions.SelectedValue))
{
IsDefault = true;
}
if (!ConvertClass.BooleanWrapper(rbtDownloadOptions.SelectedValue))
{
IsThumbnail = true;
}
FileNameList.Clear();
#endregion
#region Get gift picture file into zip file
XmlDocument mXMLDocument = new XmlDocument();
mXMLDocument.LoadXml(GiftIDs);
XmlNodeList NodeList = mXMLDocument.SelectNodes("//items/item");
foreach (XmlNode idNode in NodeList)
{
#region Get image stream
// Get Image Data
DataSet ds = DataSource;
if (ds.Tables.Count == 0)
{
continue;
}
if (ds.Tables[0].Rows.Count == 0)
{
continue;
}
DataRow dr = ds.Tables[0].Rows[0];
#endregion
// This is how to get the data out of the stream
byte[] buffer = (byte[])dr["GiftPicture"];
MemoryStream stream = new MemoryStream(buffer);
// Create the zip entry
string entryName = string.Empty;
if (ConvertClass.BooleanWrapper(rbtFileNameOptions.SelectedValue))
{
GiftEntity CurrentGift = new GiftEntity();
CurrentGift.GiftID = ConvertClass.Int32Wrapper(idNode.Attributes["id"].Value);
CurrentGift = DataSource;
entryName = CurrentGift.GiftReference + GetFileExtensionName(dr["GiftPictureFileName"].ToString());
}
else
{
entryName = dr["GiftPictureFileName"].ToString();
}
ZipEntry entry = new ZipEntry(GetNonDuplicatedNameOfFile(entryName, 1));
entry.DateTime = DateTime.Now;
entry.Size = buffer.Length;
// Use CRC to format the buffer
Crc32 objCrc32 = new Crc32();
objCrc32.Reset();
objCrc32.Update(buffer);
entry.Crc = objCrc32.Value;
// Write the zip file
MyZipStream.PutNextEntry(entry);
MyZipStream.Write(buffer, 0, buffer.Length);
stream.Close();
}
#endregion
#region Generate zip file
MyZipStream.Finish();
MyZipStream.Close();
// We have created the zip file and now it's time to serve it
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + txtZIPFileName.Text + ".zip");
Response.ContentType = "application/x-zip-compressed";
byte[] ZipBuffer = new byte[ziparchive.Length - 1];
ZipBuffer = ziparchive.GetBuffer();
Response.OutputStream.Write(ZipBuffer, 0, Convert.ToInt32(ziparchive.Length));
Response.End();
MyZipStream.Close();
#endregion