0

i am using ICSharpCode.SharpZipLib.Zip to compress the files & download zip file, and here using SQL File stream to store any kind of file(any amount of GB). Then, how can i zip the files from sql file stream and get download... And i tried something like below, which is throwing an exception "size was 845941, but I expected 16 at ICSharpCode.SharpZipLib.Zip.ZipOutputStream.CloseEntry()".How to solve this...

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();
Jilani pasha
  • 389
  • 3
  • 14

1 Answers1

0

After Understanding each line of code, i figured out the solution..

1) "zipEntry.Size = model123.serverTxn.Length;" this line is causing the exception as "size was 845941, but I expected 16"..because "model123.serverTxn.Length" is not the complete size of the file., So i changed this to "sfs.Length" which is SqlFileStream length.

2) zipOutputStream level is set maximum as "zipOutputStream.SetLevel(9)" because, i am zipping the large size files here like videos..

3) And TransactionScope has to be more, other wise the complete file(large files more than 500mb) is not going to be downloaded hence we will see file damaged error message after downloading..

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)...";
 }
Jilani pasha
  • 389
  • 3
  • 14
  • You don't need to compress anything to store big files (BLOBs). That's what `varchar(max) and FILESTREAM support is for. As for compression, SQL Server 2016 introduced the [COMPRESS/DECOMPRESS](https://learn.microsoft.com/en-us/sql/t-sql/functions/compress-transact-sql) command for GZIP compression. Table compression was already available – Panagiotis Kanavos Jan 23 '18 at 09:50
  • initially i tried with c# stream to store the large file, but i am not able store larger files more than 1GB even..but i can do that with sqlfilestream... – Jilani pasha Jan 23 '18 at 10:08