创建ZIP文件然后发送给客户

时间:2015-06-10 08:02:34

标签: c# asp.net compression zip export

我的网页上有一个按钮,可以导出CSV文件。共有5个文件。当客户端单击该按钮时,服务器将创建文件,将它们压缩成一个ZIP文件,然后将ZIP文件发送到客户端进行下载。

我在论坛上听说过SharpZipLabDotNetZip,但我还没有探讨过。我也听说过使用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

1 个答案:

答案 0 :(得分:0)

Sachu 的帮助下,我们完成了这项要求。由于许可问题,我们使用DotNetZip而不是SharpZipLib

为了促进我们开发此功能,我应该根据我的要求创建一个程序流程:

  1. 创建文本文件
  2. 将文本文件添加到文件夹
  3. Zip格式
  4. 压缩此文件夹
  5. 使用Response
  6. 发送给客户
  7. 删除文件
  8. 步骤0 - 设置项目

    在我们开始这个过程之前,我们必须准备好项目。这包括添加必要的文件夹和实例化变量。

    首先,我们添加一个文件夹,我们将“临时”添加文本文件。此文件夹也将是将被压缩的文件夹。我决定在项目的根目录中创建名为CSV的文件夹。

    现在我们将使用DotNetZip库。您可以下载here。将库添加到项目引用中。然后添加使用,即using Ionic.Zip;

    然后我们实例化zipFileNametextFileName等变量。这些名称不言自明。

    我将用于文本文件的数据来自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.txtfile2.txtfile3.txt等。

    第3步&amp; 4 - 压缩文件夹&amp;发送给客户

    现在我们可以进行压缩了。我们修改了第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转移到File2File2转移到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 ,一个非常有帮助的人。