阳光不锈

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::

      将大文件分块读入数据库,这是一个很好的思想,不知道可不可以应用到毕设中,二十几兆的txt要怎么分块,具体怎么实现还要再想想

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      最近一个项目需要将大文件写入和读取到数据库,我们知道sqlserver 的image列最多只能容纳2,147,483,647个字节,如果遇到超过10mb以上的数据如果想在网络上一次写进去或者读出是不可能的,第一sql server的连接时间默认是15s,即使将连接时间设置到更长的时间能够将一个文件写入或者读取到数据库,我想没有用户想对着一个毫无响动的界面傻等10多分钟或者更长的时间。所以这里我调用了存储过程来将image列或要写入的文件划分成若干数据块来上传,这样不但可以不受sql server的连接时间的限制,而且可以通过数据块来度量文件的写入或者读取的进度,其实这里如果将存储过程写在数据库可能执行数率要快一些,但我个人一直认为如果将存储过程写在数据库中,尤其是在测试阶段或者项目迁移的阶段,很有可能出现将存储过程丢失的情况,还有个重要的原因,众所周知存储过程的异常是相当不好调试的,但如果我将存储过程写入代码,我就可以通过try catch来捕获在执行存储过程的时产生的异常,这能有效的降低项目的风险提高代码的容错性。代码如下

protected int state = 0; //表示进度条当前处理的事件类型,1表读取word,2表写入word,3表doc转pdf,4表txt转pdf

private System.Windows.Forms.Form getDialog(string strFormName,System.Drawing.Icon ico,string strShowContent)
   {
    System.Windows.Forms.Form frm = new Form();
    //初始化窗体
    frm.Text = strFormName;
    frm.Icon = ico;
    frm.MaximizeBox = false;
    frm.MinimizeBox = false;
    frm.TopMost = true;
    frm.ShowInTaskbar = false;
    frm.Height = 168;
    frm.Width = 544;
    frm.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;

    //添加控件
    System.Windows.Forms.Label lblContent = new Label();
    lblContent.Text = strShowContent;
            lblContent.Left = 30;
    lblContent.Top = 20;
    lblContent.Text = strShowContent;
    frm.Controls.Add(lblContent);
           
            System.Windows.Forms.ProgressBar prgLoader = new ProgressBar();
    prgLoader.Left=30;
    prgLoader.Top = lblContent.Top + lblContent.Height + 5;
    prgLoader.Width = frm.Width - 2 * 30;
    frm.Controls.Add(prgLoader);
  
    System.Windows.Forms.Label lblShowPercent = new Label();
    lblShowPercent.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
    lblShowPercent.Left = prgLoader.Width + 30 - lblShowPercent.Width;
    lblShowPercent.Top = prgLoader.Height + prgLoader.Top + 5;
            lblShowPercent.Text = prgLoader.Value.ToString() + "%";
    lblShowPercent.Name = "lblShowPercent";
    frm.Controls.Add(lblShowPercent);

    System.Windows.Forms.Button btnOK = new Button();
    btnOK.Text = "取消";
    btnOK.Left = prgLoader.Width + 30 - btnOK.Width;
    btnOK.Top = frm.Height - 30 - btnOK.Height;
    btnOK.Click +=new EventHandler(btnOk_Click);
    frm.Controls.Add(btnOK);
           
    return frm;
   }

   private void btnOk_Click(object sender,System.EventArgs e)
   {
     //获取控件信息
    System.Windows.Forms.Button btnOk = (System.Windows.Forms.Button)sender;
     System.Windows.Forms.Form frm = (System.Windows.Forms.Form)btnOk.Parent;
    System.Windows.Forms.ProgressBar prgLoader = null;
    foreach(System.Windows.Forms.Control control in frm.Controls)
    {
     if(control.GetType().ToString() == "System.Windows.Forms.ProgressBar")
     {
      prgLoader = (System.Windows.Forms.ProgressBar)control;
     }
    }
    //判断当前的完成情况
    if(prgLoader.Value == 100)
    {
     frm.Close();
    }
    else
    {
     System.Windows.Forms.DialogResult dr = MessageBox.Show(frm,"是否停止当前操作?","提示",System.Windows.Forms.MessageBoxButtons.YesNo,
      System.Windows.Forms.MessageBoxIcon.Warning);
     if(dr == System.Windows.Forms.DialogResult.Yes)
     {
      state = 0;
      frm.Close();   
     }

    }
   }

/// <summary>
        /// 写入word到数据库
        /// </summary>
        /// <param name="sqlcon">sql连接类</param>
        /// <param name="strTargetInsert">直接将目标内容写入数据库的sql,"insert into 表名(目标列名) values (@block)"</param>
        /// <param name="strTargetHandle">获取目标内容的句柄的sql,"select @content=textptr(目标列名) from 目标表名 where 条件"</param>
        /// <param name="strTableName">目标表名</param>
        /// <param name="strColumnName">目标列名</param>
        /// <param name="strPath">要读取word的路径</param>
        /// <param name="intSetBlock">定义块大小</param>
   /// <param name="bolShowDialog">是否显示进度条</param>
   /// <param name="strFormName">窗体名称</param>
   /// <param name="ico">窗体图标</param>
   /// <param name="strShowContent">显示内容</param>
        /// <returns>true表成功</returns>
   public bool WriteWordDocument(System.Data.SqlClient.SqlConnection sqlcon,string strTargetInsert,string strTargetHandle,string strTableName,string strColumnName,string strPath,int intSetBlock,bool bolShowDialog,string strFormName,System.Drawing.Icon ico,string strShowContent)
   {
    //初始化SqlCommand
    System.Data.SqlClient.SqlCommand sqlcmd = new System.Data.SqlClient.SqlCommand();
    sqlcmd.Connection = sqlcon;
    sqlcmd.CommandType = System.Data.CommandType.Text;

    int intBlock = intSetBlock; //块大小
    int intCount = 0; //分快数
    int intLength = 0; //获取文件内容的长度
    string strSelect = ""; //要执行的sql查询语句
    byte []bytContent = null; //定义内容数组
    //比例
      int intPercent = 0;
    //建立要输入的文件流
            System.IO.FileStream fs = null;
    //建立二进制读取
    System.IO.BinaryReader br = null;
    try
    {
     fs = new FileStream(strPath,System.IO.FileMode.Open);
    }
    catch
    {
     return false;
    }
    br = new BinaryReader((Stream)fs);
            //为关键参数赋值
    try
    {
     //是否显示进度
     if(bolShowDialog)
     {
      //获取精度窗体,引用窗体中的进度条和按钮控件
      System.Windows.Forms.Form frmProgress = getDialog(strFormName,ico,strShowContent);
      System.Windows.Forms.ProgressBar prgLoader = null;
      System.Windows.Forms.Button btnOk = null;
      System.Windows.Forms.Label lblShowPercent = null;
      foreach(System.Windows.Forms.Control control in frmProgress.Controls)
      {
       if(control.GetType().ToString() == "System.Windows.Forms.ProgressBar")
       {
        prgLoader = (System.Windows.Forms.ProgressBar)control;
       }
       if(control.GetType().ToString() == "System.Windows.Forms.Button")
       {
        btnOk = (System.Windows.Forms.Button)control;
       }
       if(control.GetType().ToString() == "System.Windows.Forms.Label" && control.Name == "lblShowPercent")
       {
        lblShowPercent = (System.Windows.Forms.Label)control;
       }
      }
    
      frmProgress.Show();
      //启动转换
      state = 2;

      if(fs.Length > 2147483647 || fs.Length == 0) //因为image列最多只能存储2,147,483,647个字节,所以这里做限定
      {
       return false;
      }
      intLength = (int)fs.Length;
      intCount = intLength / intBlock;

      if(intCount == 0)
      {
       strSelect = strTargetInsert;
       bytContent = new byte[intLength];
       bytContent = br.ReadBytes(intLength);
       sqlcmd.CommandText = strSelect;
       sqlcmd.Parameters.Add("@block",System.Data.SqlDbType.Image).Value = bytContent;
       sqlcmd.ExecuteNonQuery();

      }
      else
      {
       strSelect = strTargetInsert;
       bytContent = new byte[intBlock];
       bytContent = br.ReadBytes(intBlock);
       sqlcmd.CommandText = strSelect;
       sqlcmd.Parameters.Add("@block",System.Data.SqlDbType.Image).Value = bytContent;
       sqlcmd.Parameters.Add("@length",System.Data.SqlDbType.Int).Value = 0;
       sqlcmd.ExecuteNonQuery();
           
       int i = 1;
       while(i != intCount)
       {
        if(state == 0)
        {
         strSelect = "delete from " + strTableName + strTargetHandle.Substring(strTargetHandle.LastIndexOf(" where "));
         sqlcmd.CommandText = strSelect;
         sqlcmd.ExecuteNonQuery();
         bytContent = null;
         fs.Close();
         return false;
        }
        strSelect = "declare @content varbinary(16) ";
        strSelect += strTargetHandle;
        strSelect += " updatetext " + strTableName + "." + strColumnName + " @content @length 0 @block";
      
        bytContent = br.ReadBytes(intBlock);

        sqlcmd.Parameters["@block"].Value = bytContent;
        sqlcmd.Parameters["@length"].Value = i * intBlock;
        sqlcmd.CommandText = strSelect;
        sqlcmd.ExecuteNonQuery();
      
        intPercent = (int)(((double)(i * intBlock)) / ((double)intLength) * 100);
        prgLoader.Value = intPercent;
        lblShowPercent.Text = prgLoader.Value.ToString() + "%";
        ++i;
        Application.DoEvents();
       }

       int intResidual = intLength % intBlock;
       if(intResidual > 0)
       {
        strSelect = "declare @content varbinary(16) ";
        strSelect += strTargetHandle;
        strSelect += " updatetext " + strTableName + "." + strColumnName + " @content @length 0 @block";

        bytContent = new byte[intResidual];
        bytContent = br.ReadBytes(intResidual);
                   
        sqlcmd.Parameters["@block"].Value = bytContent;
        sqlcmd.Parameters["@length"].Value = intCount * intBlock;
        sqlcmd.CommandText = strSelect;
        sqlcmd.ExecuteNonQuery();   
       }
      }
      prgLoader.Value = 100;
      lblShowPercent.Text = prgLoader.Value.ToString() + "%";
      btnOk.Text = "关闭";

     }
     else
     {
      if(fs.Length > 2147483647 || fs.Length == 0) //因为image列最多只能存储2,147,483,647个字节,所以这里做限定
      {
       return false;
      }
      intLength = (int)fs.Length;
      intCount = intLength / intBlock;

      if(intCount == 0)
      {
       strSelect = strTargetInsert;
       bytContent = new byte[intLength];
       bytContent = br.ReadBytes(intLength);
       sqlcmd.CommandText = strSelect;
       sqlcmd.Parameters.Add("@block",System.Data.SqlDbType.Image).Value = bytContent;
       sqlcmd.ExecuteNonQuery();
      }
      else
      {
       strSelect = strTargetInsert;
       bytContent = new byte[intBlock];
       bytContent = br.ReadBytes(intBlock);
       sqlcmd.CommandText = strSelect;
       sqlcmd.Parameters.Add("@block",System.Data.SqlDbType.Image).Value = bytContent;
       sqlcmd.Parameters.Add("@length",System.Data.SqlDbType.Int).Value = 0;
       sqlcmd.ExecuteNonQuery();
   
       int i = 1;
       while(i != intCount)
       {
        strSelect = "declare @content varbinary(16) ";
        strSelect += strTargetHandle;
        strSelect += " updatetext " + strTableName + "." + strColumnName + " @content @length 0 @block";
      
        bytContent = br.ReadBytes(intBlock);

        sqlcmd.Parameters["@block"].Value = bytContent;
        sqlcmd.Parameters["@length"].Value = i * intBlock;
        sqlcmd.CommandText = strSelect;
        sqlcmd.ExecuteNonQuery();
        ++i;
       }

       int intResidual = intLength % intBlock;
       if(intResidual > 0)
       {
        strSelect = "declare @content varbinary(16) ";
        strSelect += strTargetHandle;
        strSelect += " updatetext " + strTableName + "." + strColumnName + " @content @length 0 @block";

        bytContent = new byte[intResidual];
        bytContent = br.ReadBytes(intResidual);
                   
        sqlcmd.Parameters["@block"].Value = bytContent;
        sqlcmd.Parameters["@length"].Value = intCount * intBlock;
        sqlcmd.CommandText = strSelect;
        sqlcmd.ExecuteNonQuery();   
       }
      }
     }
     bytContent = null;
     fs.Close();
    }
    catch
    {
     state = 0;
     bytContent = null;
     fs.Close();
     return false;
    }
    state = 0;
    return true;
   }

        /// <summary>
        /// 从数据库读取word
        /// </summary>
        /// <param name="sqlcon">sql连接类</param>
        /// <param name="strTargetSelect">直接获取目标内容的sql,"select 目标列名 from 目标表名 where 条件"</param>
        /// <param name="strTargetLength">获取目标内容的长度的sql,"select datalength(目标列名) from 目标表名 where 条件"</param>
        /// <param name="strTargetHandle">获取目标内容的句柄的sql,"select @content=textptr(目标列名) from 目标表名 where 条件"</param>
        /// <param name="strTableName">目标表名</param>
        /// <param name="strColumnName">目标列名</param>
        /// <param name="strPath">要导出并保存的word的路径</param>
        /// <param name="intSetBlock">定义块大小</param>
   /// <param name="bolShowDialog">是否显示进度条</param>
   /// <param name="strFormName">窗体名称</param>
   /// <param name="ico">窗体图标</param>
   /// <param name="strShowContent">显示内容</param>
        /// <returns>true表成功</returns>
   public bool ReadWordDocument(System.Data.SqlClient.SqlConnection sqlcon,string strTargetSelect,string strTargetLength,string strTargetHandle,string strTableName,string strColumnName,string strPath,int intSetBlock,bool bolShowDialog,string strFormName,System.Drawing.Icon ico,string strShowContent)
   {
    //初始化SqlCommand
            System.Data.SqlClient.SqlCommand sqlcmd = new System.Data.SqlClient.SqlCommand();
            sqlcmd.Connection = sqlcon;
    sqlcmd.CommandType = System.Data.CommandType.Text;

    int intBlock = intSetBlock; //块大小
    int intCount = 0; //分快数
    int intLength = 0; //获取的image列中的内容的长度
    string strSelect = ""; //要执行的sql查询语句
    byte []bytContent = null; //定义内容数组
    int intPercent = 0; //获取读取的比例
    //建立要输出的文件流
    System.IO.FileStream fs = new FileStream(strPath,System.IO.FileMode.Create);

    try
    {
     //获取指定image列中的内容长度
     sqlcmd.CommandText = strTargetLength;
     intLength = (int)sqlcmd.ExecuteScalar();
     //如果长度为0
     if(intLength == 0)
     {
      return false;
     }
     //获得分快数
     intCount = intLength / intBlock;

                //是否显示精度
     if(bolShowDialog)
     {
      //获取精度窗体,引用窗体中的进度条和按钮控件
      System.Windows.Forms.Form frmProgress = getDialog(strFormName,ico,strShowContent);
      System.Windows.Forms.ProgressBar prgLoader = null;
      System.Windows.Forms.Button btnOk = null;
      System.Windows.Forms.Label lblShowPercent = null;
      foreach(System.Windows.Forms.Control control in frmProgress.Controls)
      {
       if(control.GetType().ToString() == "System.Windows.Forms.ProgressBar")
       {
        prgLoader = (System.Windows.Forms.ProgressBar)control;
       }
       if(control.GetType().ToString() == "System.Windows.Forms.Button")
       {
        btnOk = (System.Windows.Forms.Button)control;
       }
       if(control.GetType().ToString() == "System.Windows.Forms.Label" && control.Name == "lblShowPercent")
       {
        lblShowPercent = (System.Windows.Forms.Label)control;
       }
      }
    
      frmProgress.Show();
      //启动转换
      state = 1;
      if(intCount == 0)
      {
       strSelect = strTargetSelect;
       sqlcmd.CommandText = strSelect;
       bytContent = new byte[intLength];
       bytContent = sqlcmd.ExecuteScalar() as byte[];
       fs.Write(bytContent,0,intLength);
       prgLoader.Value = 100;
       lblShowPercent.Text = prgLoader.Value + "%";
       btnOk.Text = "关闭";
     
      }
      else
      {
       int i = 0;
       bytContent = new byte[intBlock];
       while(i < intCount)
       {
        if(state == 0)
        {
         bytContent = null;
         System.IO.File.Delete(strPath);
         fs.Close();
         return false;
        }
        strSelect = "declare @content varbinary(16) "; //再sql中声明获取目标image列内容的句柄变量
        strSelect += strTargetHandle; //获取句柄
        //锁定并读取指定长度的数据
        strSelect += " readtext " + strTableName + "." + strColumnName + " @content @start @count HOLDLOCK";
        if(i == 0)
        {
         //添加@start和@count变量,分别表偏移变量和取的长度
         sqlcmd.Parameters.Add("@start",System.Data.SqlDbType.Int).Value = 0;
         sqlcmd.Parameters.Add("@count",System.Data.SqlDbType.Int).Value = intBlock;
        }
        else
        {
         sqlcmd.Parameters["@start"].Value = i * intBlock;
         sqlcmd.Parameters["@count"].Value = intBlock;
        }
        sqlcmd.CommandText = strSelect;
        bytContent = sqlcmd.ExecuteScalar() as byte[];
        fs.Write(bytContent,0,intBlock);
        intPercent = (int)(((double)(i * intBlock)) / (double)(intLength) * 100);
        prgLoader.Value = intPercent;
        lblShowPercent.Text = prgLoader.Value.ToString() + "%";
        Application.DoEvents();
        ++i;
       }
       //将剩余的字节写入流
       int intResidual = intLength % intBlock;
       if(intResidual > 0)
       {
        strSelect = "declare @content varbinary(16) "; //再sql中声明获取目标image列内容的句柄变量
        strSelect += strTargetHandle; //获取句柄
        //锁定并读取指定长度的数据
        strSelect += " readtext " + strTableName + "." + strColumnName + " @content @start @count HOLDLOCK";
        bytContent = new byte[intResidual];
        sqlcmd.Parameters["@start"].Value = intCount * intBlock;
        sqlcmd.Parameters["@count"].Value = intResidual;
        sqlcmd.CommandText = strSelect;
        bytContent = sqlcmd.ExecuteScalar() as byte[];
        fs.Write(bytContent,0,intResidual);
      
       }
       prgLoader.Value = 100;
       lblShowPercent.Text = prgLoader.Value.ToString() + "%";
       btnOk.Text = "关闭";
      }
     }
     else
     {
      if(intCount == 0)
      {
       strSelect = strTargetSelect;
       sqlcmd.CommandText = strSelect;
       bytContent = new byte[intLength];
       bytContent = sqlcmd.ExecuteScalar() as byte[];
       fs.Write(bytContent,0,intLength);
      }
      else
      {
       int i = 0;
       bytContent = new byte[intBlock];
       while(i < intCount)
       {
        strSelect = "declare @content varbinary(16) "; //再sql中声明获取目标image列内容的句柄变量
        strSelect += strTargetHandle; //获取句柄
        //锁定并读取指定长度的数据
        strSelect += " readtext " + strTableName + "." + strColumnName + " @content @start @count HOLDLOCK";
        if(i == 0)
        {
         //添加@start和@count变量,分别表偏移变量和取的长度
         sqlcmd.Parameters.Add("@start",System.Data.SqlDbType.Int).Value = 0;
         sqlcmd.Parameters.Add("@count",System.Data.SqlDbType.Int).Value = intBlock;
        }
        else
        {
         sqlcmd.Parameters["@start"].Value = i * intBlock;
         sqlcmd.Parameters["@count"].Value = intBlock;
        }
        sqlcmd.CommandText = strSelect;
        bytContent = sqlcmd.ExecuteScalar() as byte[];
        fs.Write(bytContent,0,intBlock);
        ++i;

       }
       //将剩余的字节写入流
       int intResidual = intLength % intBlock;
       if(intResidual > 0)
       {
        strSelect = "declare @content varbinary(16) "; //再sql中声明获取目标image列内容的句柄变量
        strSelect += strTargetHandle; //获取句柄
        //锁定并读取指定长度的数据
        strSelect += " readtext " + strTableName + "." + strColumnName + " @content @start @count HOLDLOCK";
        bytContent = new byte[intResidual];
        sqlcmd.Parameters["@start"].Value = intCount * intBlock;
        sqlcmd.Parameters["@count"].Value = intResidual;
        sqlcmd.CommandText = strSelect;
        bytContent = sqlcmd.ExecuteScalar() as byte[];
        fs.Write(bytContent,0,intResidual);

       }
      }

     }
      bytContent = null;
      fs.Close();
    }
    catch
    {
      state = 0;
      System.IO.File.Delete(strPath);
                  bytContent = null;
                  fs.Close();
      return false;
    }
    state = 0;
    return true;
   }

posted on 2009-05-11 10:02  靳小透  阅读(1348)  评论(1编辑  收藏  举报