我的网页上有一个按钮,可以导出CSV文件。共有5个文件。当客户端单击该按钮时,服务器将创建文件,将它们压缩成一个ZIP文件,然后将ZIP文件发送到客户端进行下载。
我在论坛上听说过SharpZipLab
和DotNetZip
,但我还没有探讨过。我也听说过使用System.IO.Compression
。您会推荐以下哪种方法?
我有这段代码来创建5个CSV文件:
StringBuilder sb = new StringBuilder();
DataTable[] dtCSV =
{
file1BLO.SelectFile1ForCSV(),
file2BLO.SelectFile2ForCSV(),
file3BLO.SelectFile3ForCSV(),
file4BLO.SelectFile4ForCSV(),
file5BLO.SelectFile5ForCSV()
};
for (int i = 0; i <= 4; i++)
{
DataTable dt = dtCSV[i];
foreach (DataRow dr in dt.Rows)
{
string[] fields = dr.ItemArray.Select(field => field.ToString()).ToArray();
sb.AppendLine(string.Join("|", fields));
}
Response.ContentType = "application/text";
Response.AddHeader("content-disposition", "attachment;filename=CAPRES-FILE" +
(i + 1) + "-" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".txt");
Response.Output.Write(sb);
Response.Flush();
sb.Clear();
}
Response.End();
编辑我正在使用ASP.NET v4.0。
编辑2 显然我有System.IO.Compression
,这很奇怪,因为我只是在v4.5中支持它。巧合的是,我没有System.IO.Packaging
。
答案 0 :(得分:0)
在 Sachu 的帮助下,我们完成了这项要求。由于许可问题,我们使用DotNetZip
而不是SharpZipLib
。
为了促进我们开发此功能,我应该根据我的要求创建一个程序流程:
Zip
格式Response
在我们开始这个过程之前,我们必须准备好项目。这包括添加必要的文件夹和实例化变量。
首先,我们添加一个文件夹,我们将“临时”添加文本文件。此文件夹也将是将被压缩的文件夹。我决定在项目的根目录中创建名为CSV
的文件夹。
现在我们将使用DotNetZip
库。您可以下载here。将库添加到项目引用中。然后添加使用,即using Ionic.Zip;
。
然后我们实例化zipFileName
,textFileName
等变量。这些名称不言自明。
我将用于文本文件的数据来自DataTable[]
数组,每个DataTable
对应一个特定的SQL查询。
DataTable[] dtCSV =
{
file1BLO.SelectFile1ForCSV(),
file2BLO.SelectFile2ForCSV(),
file3BLO.SelectFile3ForCSV(),
file4BLO.SelectFile4ForCSV(),
file5BLO.SelectFile5ForCSV()
};
StringBuilder sb = new StringBuilder();
string textFileNameTemplate = Server.MapPath(@"~\CSV") + @"\file";
Response.Clear();
Response.BufferOutput = false;
Response.ContentType = "application/zip";
Response.AppendHeader("content-disposition", "attachment;filename=CAPRES-" +
DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".zip");
这很容易。我使用StringBuilder
来转换DataTables
的结果。使用这个,然后我使用StreamWriter
自己构建文本文件。
for (int i = 0; i <= 4; i++)
{
DataTable dt = dtCSV[i];
foreach (DataRow dr in dt.Rows)
{
string[] fields = dr.ItemArray.Select(field => field.ToString()).ToArray();
sb.AppendLine(string.Join("|", fields));
}
string textFileName = textFileNameTemplate + (i + 1) + ".txt";
var textFile = new StreamWriter(textFileName);
textFile.WriteLine(sb.ToString());
textFile.Flush();
textFile.Close();
}
注意我是如何使用textFileNameTemplate
变量的。我附加了迭代器和.txt
文件扩展名。因此,我们会将文件命名为file1.txt
,file2.txt
,file3.txt
等。
现在我们可以进行压缩了。我们修改了第2步中的代码以适应库。
using (ZipFile zip = new ZipFile()) //encapsulate Step 2 code in this code block
{
for (int i = 0; i <= 4; i++)
{
DataTable dt = dtCSV[i];
foreach (DataRow dr in dt.Rows)
{
string[] fields = dr.ItemArray.Select(field => field.ToString()).ToArray();
sb.AppendLine(string.Join("|", fields));
}
string textFileName = textFileNameTemplate + (i + 1) + ".txt";
var textFile = new StreamWriter(textFileName);
textFile.WriteLine(sb.ToString());
textFile.Flush();
textFile.Close();
sb.Clear();
zip.AddFile(textFileName, @"\"); //this is new
}
zip.Save(Response.OutputStream); //this is also new
}
Response.Flush();
Response.End();
zip.AddFile(textFileName, @"\");
将文本文件添加到存档中。 @"\"
表示DotNetZip
不会创建指向该文件的子文件夹,例如如果我的文件位于此路径中:C:\User\Documents\...\file1.txt
,则存档将具有类似的文件夹结构。使用@"\"
时,存档将仅包含文本文件。
另请注意sb.Clear();
及其在代码中的位置。重要的是它在for循环中但在textFile.WriteLine(sb.ToString());
行之后。这可以确保在再次循环之前清除之前写入的字符串。这样可以避免将字符串从File1
转移到File2
,File2
转移到File3
,依此类推。
zip.Save(Response.OutputStream);
会直接将Zip文件输出到Response
,并且不会将文件保存在服务器中。
此步骤取决于您的要求。对我来说,我们将删除生成的文件。使用System.IO.File
,我们将删除文本文件。在using ZipFile zip = new ZipFile())
代码块之后,我们将添加以下行:
for (int i = 1; i <= 5; i++)
{
File.Delete(textFileNameTemplate + i + ".txt");
}
我的代码可能不是最优化的代码。但它的确有效。如果有人可以建议一个更好的代码。但是现在,我将使用这段代码。非常感谢!特别是对 Sachu ,一个非常有帮助的人。