创建 ZIP 文件然后发送给客户端
Create ZIP File Then Send to Client
我的网页中有一个按钮可以导出 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
.
在Sachu的帮助下,我们完成了这个要求。由于许可问题,我们使用 DotNetZip
而不是 SharpZipLib
。
为了方便我们开发这个功能,我应该根据我的要求创建一个程序流程:
- 创建文本文件
- 将文本文件添加到文件夹
- 以
Zip
格式压缩此文件夹
- 使用
Response
发送给客户端
- 删除文件
步骤 0 - 安装项目
在我们开始这个过程之前,我们必须准备项目。这包括添加必要的文件夹和实例化变量。
首先我们添加一个文件夹,我们将 'temporarily' 添加文本文件。该文件夹也将被压缩。我决定在项目的根目录中创建名为 CSV
.
的文件夹
现在我们将使用 DotNetZip
库。你可以下载它here。将库添加到您的项目引用中。然后加上using,就是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");
第 1 步 - 创建文本文件
这很容易。我使用 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
等的文件
第 3 步和第 4 步 - 压缩文件夹并发送给客户端
现在我们可以继续压缩了。我们修改了步骤 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
而不会在服务器中保存文件。
第 5 步 - 删除文件
这一步取决于您的要求。对我来说,我们将删除生成的文件。使用 System.IO.File
,我们将删除文本文件。在 using ZipFile zip = new ZipFile())
代码块之后,我们将添加以下行:
for (int i = 1; i <= 5; i++)
{
File.Delete(textFileNameTemplate + i + ".txt");
}
我的代码可能不是最优化的代码。但它有效。如果有人可以建议更好的代码,那就太好了。但现在,我将使用这段代码。非常感谢!特别是 Sachu,一个非常乐于助人的人。
我的网页中有一个按钮可以导出 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
.
在Sachu的帮助下,我们完成了这个要求。由于许可问题,我们使用 DotNetZip
而不是 SharpZipLib
。
为了方便我们开发这个功能,我应该根据我的要求创建一个程序流程:
- 创建文本文件
- 将文本文件添加到文件夹
- 以
Zip
格式压缩此文件夹 - 使用
Response
发送给客户端
- 删除文件
步骤 0 - 安装项目
在我们开始这个过程之前,我们必须准备项目。这包括添加必要的文件夹和实例化变量。
首先我们添加一个文件夹,我们将 'temporarily' 添加文本文件。该文件夹也将被压缩。我决定在项目的根目录中创建名为 CSV
.
现在我们将使用 DotNetZip
库。你可以下载它here。将库添加到您的项目引用中。然后加上using,就是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");
第 1 步 - 创建文本文件
这很容易。我使用 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
等的文件
第 3 步和第 4 步 - 压缩文件夹并发送给客户端
现在我们可以继续压缩了。我们修改了步骤 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
而不会在服务器中保存文件。
第 5 步 - 删除文件
这一步取决于您的要求。对我来说,我们将删除生成的文件。使用 System.IO.File
,我们将删除文本文件。在 using ZipFile zip = new ZipFile())
代码块之后,我们将添加以下行:
for (int i = 1; i <= 5; i++)
{
File.Delete(textFileNameTemplate + i + ".txt");
}
我的代码可能不是最优化的代码。但它有效。如果有人可以建议更好的代码,那就太好了。但现在,我将使用这段代码。非常感谢!特别是 Sachu,一个非常乐于助人的人。