0

我正在使用 ICSharpCode.SharpZipLib.Zip 压缩文件并下载 zip 文件,这里使用 SQL 文件流来存储任何类型的文件(任何数量的 GB)。然后,我如何从 sql 文件流中压缩文件并下载...我尝试了类似下面的方法,它抛出异常“大小为 845941,但我预计 ICSharpCode.SharpZipLib.Zip.ZipOutputStream.CloseEntry 为 16( )"。如何解决这个问题...

string zipFileName = "ZipName.zip";
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "fileName=" + zipFileName);
byte[] buffer = new byte[4096];
ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(3);

string cs = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
foreach (Filec file1 in Files)
 {
   StreamModel model123 = new StreamModel();
   const string SelectTSql = @"
        SELECT FileData.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT(), FileType
         FROM MyFiles WHERE FileId = @FileId";

   using (TransactionScope ts = new TransactionScope())
    {
     using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(cs))
     {
      conn.Open();

      using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(SelectTSql, conn))
       {
        cmd.Parameters.Add("@FileId", System.Data.SqlDbType.Int).Value = Convert.ToInt32(file1.FileId);
        using (System.Data.SqlClient.SqlDataReader rdr = cmd.ExecuteReader())
         {
           rdr.Read();
           model123.serverPath = rdr.GetSqlString(0).Value;
           model123.serverTxn = rdr.GetSqlBinary(1).Value;
           model123.filetype = rdr.GetSqlString(2).Value;
           rdr.Close();
         }
        }
      }
 ZipEntry zipEntry = new ZipEntry(ZipEntry.CleanName(file1.FileName));
 zipEntry.Size = model123.serverTxn.Length;
 zipOutputStream.PutNextEntry(zipEntry);
 byte[] buffer3 = new byte[4096];
 using (System.Data.SqlTypes.SqlFileStream sfs = new System.Data.SqlTypes.SqlFileStream(model123.serverPath, model123.serverTxn, FileAccess.Read))
  {
    int bytesRead;
    while ((bytesRead = sfs.Read(buffer3, 0, buffer3.Length)) > 0)
      {
         zipOutputStream.Write(buffer3, 0, bytesRead);
      }
    sfs.Close();
  }
 zipOutputStream.CloseEntry(); // at this line throwing an exception.
 ts.Complete();
   }
}
zipOutputStream.Close();
Response.Flush();
Response.End();
4

1 回答 1

0

在理解了每一行代码之后,我想出了解决方案..

1) "zipEntry.Size = model123.serverTxn.Length;" 此行导致异常为“大小为 845941,但我预计为 16”..因为“model123.serverTxn.Length”不是文件的完整大小。所以我将其更改为“sfs.Length”,即 SqlFileStream长度。

2) zipOutputStream 级别设置为“zipOutputStream.SetLevel(9)”的最大值,因为我在这里压缩大尺寸文件,如视频..

3) TransactionScope 必须更多,否则将无法下载完整的文件(超过 500mb 的大文件),因此我们会在下载后看到文件损坏的错误消息。

string zipFileName = "ZipName.zip";
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "fileName=" + zipFileName);
byte[] buffer = new byte[4096];
ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(9);     // Point 2

try
 {
   string cs = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
   foreach (Filec file1 in Files)
    {
     StreamModel model123 = new StreamModel();
     const string SelectTSql = @"SELECT FileData.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT(), FileType
                         FROM MyFiles WHERE FileId = @FileId";
     using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required,
      new TransactionOptions { Timeout = TimeSpan.FromDays(1) })) // Point 3
        {
         using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(cs))
          {
            conn.Open();
          using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(SelectTSql, conn))
           {
             cmd.Parameters.Add("@FileId", System.Data.SqlDbType.Int).Value = Convert.ToInt32(file1.FileId);
           using (System.Data.SqlClient.SqlDataReader rdr = cmd.ExecuteReader())
            {
              rdr.Read();
              model123.serverPath = rdr.GetSqlString(0).Value;
              model123.serverTxn = rdr.GetSqlBinary(1).Value;
              model123.filetype = rdr.GetSqlString(2).Value;
              rdr.Close();
            }
           }
          }
      using (System.Data.SqlTypes.SqlFileStream sfs = new System.Data.SqlTypes.SqlFileStream(model123.serverPath, model123.serverTxn, FileAccess.Read))
        {
          ZipEntry zipEntry = new ZipEntry(ZipEntry.CleanName(file1.FileName));
          zipEntry.Size = sfs.Length;      // Point 1
          zipOutputStream.PutNextEntry(zipEntry);
          int bytesRead;
          while ((bytesRead = sfs.Read(buffer, 0, buffer.Length)) > 0)
           {
            if (!Response.IsClientConnected)
              {
                  break;
              }
            zipOutputStream.Write(buffer, 0, bytesRead);
            Response.Flush();
           }
             sfs.Close();
         }

    ts.Complete();
  }
    zipOutputStream.CloseEntry();
 }

  zipOutputStream.Finish();
  zipOutputStream.Close();
  Response.Flush();
  Response.End();
}
catch (Exception ex)
 {
   TempData["ErrorMessage"] = "Oohhhh! Exception Occured(Error)...";
 }
于 2018-01-23T09:37:45.850 回答