• c# 操作文件存入数据库(以二进制形式存入)


      在开发的过程中,经常会遇到将文件存入数据库的形式,一般常用方法是将文件上传至服务器,数据库只需保存文件路径地址即可,但是很多内部window应用并不链接网络都是本地运行服务,那么此时我们存储文件就需要用到另一种形式,即将文件 FileStream 操作文件流的形式将文件转为字节存入数据库,下载时,在对应转换下载即可。

      本次,我们将提供两种数据库的操作方式,PostgresSql 和 Sqlite 两种数据库的存储方式。

      PostgresSql

      Psql 数据库提供了存储字节的类型,即 bytea,所以创建数据库时,要将对应的字段设置为 bytea

    1 CREATE TABLE tb_flypath 
    2 (  
    3     ID SERIAL PRIMARY KEY ,
    4     FileName TEXT NOT NULL,
    5     FileContent bytea NOT NULL,
    6     CreateTime timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP
    7 )

      那么,设置为 bytea 后就可以将文件转为字节进行存储了,使用以下代码

     1         /// <summary>
     2         /// 将文件转为字节
     3         /// </summary>
     4         /// <param name="path">文件路径</param>
     5         /// <returns></returns>
     6         public byte[] getContent(string path)
     7         {
     8             System.IO.FileStream fs = new System.IO.FileStream(@path, System.IO.FileMode.Open);
     9             fs.Position = 0;
    10             byte[] content = new byte[fs.Length];
    11             fs.Read(content, 0, (int)fs.Length);
    12             fs.Close();
    13             return content;
    14         }

      我们直接使用 SQL 语句,将字节转为字符串存入数据库

     1         /// <summary>
     2         /// 字节转字符串
     3         /// </summary>
     4         /// <param name="inputBytes">字节</param>
     5         /// <returns></returns>
     6         public string ByteToString(byte[] inputBytes)
     7         {
     8             StringBuilder temp = new StringBuilder(2048);
     9             foreach (byte tempByte in inputBytes)
    10             {
    11                 temp.Append(tempByte > 15 ?
    12                 Convert.ToString(tempByte, 2) : '0' + Convert.ToString(tempByte, 2));
    13             }
    14             return temp.ToString();
    15         }
    16 
    17         string bstr = ByteToString(buffer);
    18         string insertSql = string.Format(@"INSERT INTO tb_flyPath (FileContent) VALUES ('{0}')", bstr);

      以上就是将文件写入数据库的操作,但是,如果采用此方法的话,就会有问题,因为 INSERT SQL 无法识别字节的类型,所以我们是将字符串存入了对应字节类型的字段里。

      那么后续遇到的问题是,下载文件时,无论如何转换 FileContent 都无法将下载的文件打开,如果是文本的话,则出现的内容为已转换的二进制数据。

      至于为什么会出现这样,还没研究透,欢迎留言。

      所以,我又采取了以下的方式进行数据存储,使用数据库 Parameter 参数执行SQL,这种方法可以将你传入的数据直接转为对应的类型  DbType.Bytea ,此类型可以传入字节类型数据进行存储,使用这种方式后,存入的数据就可以下载后进行转换使用并打开各种文件了。

     1         /// <summary>
     2         /// 文件存储入表
     3         /// </summary>
     4         /// <param name="filePath">文件路径</param>
     5         /// <param name="id">节点ID</param>
     6         /// <returns></returns>
     7         public bool FileInsert(string filePath, string id)
     8         {
     9             string strErrMsg = "";
    10             //读取文件 
    11             FileStream fs = File.OpenRead(filePath);
    12             byte[] buffer = new byte[fs.Length];
    13             fs.Read(buffer, 0, buffer.Length);
    14 
    15             if (!CreateCommand(out strErrMsg))
    16                 return false;
    17 
    31             NpgsqlParameter paramFileContent = _Command.CreateParameter();
    32             paramFileContent.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Bytea;
    33             paramFileContent.ParameterName = "FileContent";
    34             paramFileContent.Direction = ParameterDirection.Input;
    35             paramFileContent.Value = buffer;
    36             _Command.Parameters.Add(paramFileContent);
    37 
    38             NpgsqlParameter paramFileName = _Command.CreateParameter();
    39             paramFileName.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar;
    40             paramFileName.ParameterName = "FileName";
    41             paramFileName.Direction = ParameterDirection.Input;
    42             paramFileName.Value = id;
    43             _Command.Parameters.Add(paramFileName);
    44 
    45             string sqlInsert = "INSERT INTO tb_flypath (filename,filecontent) VALUES (:FileName, :FileContent)";
    46             _Command.CommandText = sqlInsert;
    47             _Command.CommandType = CommandType.Text;
    48 
    49             _Connection.Open();
    50             int result = _Command.ExecuteNonQuery();
    51             _Connection.Close();
    52 
    53             return result > 0 ? true : false;
    54         }
    55 
    56         /// <summary> 
    57         /// 根据文件名从数据库中获取文件 
    58         /// </summary> 
    59         /// <param name="fileName">数据库中的文件名</param> 
    60         /// <param name="savePath">文件的保存路径,包括文件名,如D:\test.fly</param> 
    61         public bool DownloadFile(string fileName, string savePath)
    62         {
    63             string strErrMsg = "";
    64 
    65             if (!CreateCommand(out strErrMsg))
    66                 return false;70 
    71             string sqlSelect = "select filename, filecontent from tb_flypath where filename=:FileName";
    72             _Command.CommandText = sqlSelect;
    73             _Command.CommandType = CommandType.Text;
    74 
    75             NpgsqlParameter paramFileName = _Command.CreateParameter();
    76             paramFileName.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar;
    77             paramFileName.ParameterName = "FileName";
    78             paramFileName.Direction = ParameterDirection.Input;
    79             paramFileName.Value = fileName;
    80             _Command.Parameters.Add(paramFileName);
    81 
    82             _Connection.Open();
    83             NpgsqlDataReader dr = _Command.ExecuteReader();
    84             dr.Read();
    85             byte[] buffer = (byte[])dr["filecontent"];
    86             dr.Close();
    87             _Connection.Close();
    88 
    89             //把文件保存到指定路径 
    90             File.WriteAllBytes(savePath, buffer);
    91 
    92             return true;
    93         }

      Sqlite

      我们在讲下 Sqlite 数据库的操作方式,其实方法都一样,没什么太大区别,只是各个数据库的存储数据类型不太一样。

      Sqlite 提供了 BLOB 类型进行存储字节数据,所以创建表。

    1 CREATE TABLE tb_flyPath
    2 (
    3     ID INTEGER primary key autoincrement , 
    4     FileName VARCHAR not null ,
    5     FileContent BLOB not null ,
    6     CreateTime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
    7 )

      那么存取文件的方法大致无区别,PostgresSql 用的是 bytea 类型,那么 Sqlite 这里需要设置为 DbType.Binary 类型。

     1         /// <summary>
     2         /// 文件存储入表
     3         /// </summary>
     4         /// <param name="filePath">文件路径</param>
     5         /// <param name="id">节点ID</param>
     6         /// <returns></returns>
     7         public bool FileInsert(string filePath, string id)
     8         {
     9             string strErrMsg = "";
    10             //读取文件 
    11             FileStream fs = File.OpenRead(filePath);
    12             byte[] buffer = new byte[fs.Length];
    13             fs.Read(buffer, 0, buffer.Length);
    14 
    15             if (!CreateCommand(out strErrMsg))
    16                 return false;
    17 
    31             SQLiteParameter paramFileContent = _Command.CreateParameter();
    32             paramFileContent.DbType = DbType.Binary;
    33             paramFileContent.ParameterName = "FileContent";
    34             paramFileContent.Direction = ParameterDirection.Input;
    35             paramFileContent.Value = buffer;
    36             _Command.Parameters.Add(paramFileContent);
    37 
    38             SQLiteParameter paramFileName = _Command.CreateParameter();
    39             paramFileName.DbType = DbType.String;
    40             paramFileName.ParameterName = "FileName";
    41             paramFileName.Direction = ParameterDirection.Input;
    42             paramFileName.Value = id;
    43             _Command.Parameters.Add(paramFileName);
    44 
    45             string sqlInsert = "INSERT INTO tb_flyPath (filename,filecontent) VALUES (:FileName, :FileContent)";
    46             _Command.CommandText = sqlInsert;
    47             _Command.CommandType = CommandType.Text;
    48 
    49             _Connection.Open();
    50             int result = _Command.ExecuteNonQuery();
    51             _Connection.Close();
    52 
    53             return result > 0 ? true : false;
    54         }
    55 
    56         /// <summary> 
    57         /// 根据文件名从数据库中获取文件 
    58         /// </summary> 
    59         /// <param name="fileName">数据库中的文件名</param> 
    60         /// <param name="savePath">文件的保存路径,包括文件名,如D:\test.fly</param> 
    61         public bool DownloadFile(string fileName, string savePath)
    62         {
    63             string strErrMsg = "";
    64 
    65             if (!CreateCommand(out strErrMsg))
    66                 return false;
    67 
    71             string sqlSelect = "select filename, filecontent from tb_flyPath where filename=:FileName";
    72             _Command.CommandText = sqlSelect;
    73             _Command.CommandType = CommandType.Text;
    74 
    75             SQLiteParameter paramFileName = _Command.CreateParameter();
    76             paramFileName.DbType = DbType.String;
    77             paramFileName.ParameterName = "FileName";
    78             paramFileName.Direction = ParameterDirection.Input;
    79             paramFileName.Value = fileName;
    80             _Command.Parameters.Add(paramFileName);
    81 
    82             _Connection.Open();
    83             SQLiteDataReader dr = _Command.ExecuteReader();
    84             dr.Read();
    85             byte[] buffer = (byte[])dr["filecontent"];
    86             dr.Close();
    87             _Connection.Close();
    88 
    89             //把文件保存到指定路径 
    90             File.WriteAllBytes(savePath, buffer);
    91 
    92             return true;
    93         }

      如有讲的不对,欢迎评论留言。

  • 相关阅读:
    PHP获取指定的时间戳
    Elasticsearch
    git有用基本指令
    php中的json_decode
    有用的sql积累
    git submodule使用原理
    mysql重复插入时insert更改为update更新操作
    jpm
    awk 语句
    tomcat 发布简单的html网站
  • 原文地址:https://www.cnblogs.com/liuchenxing/p/15825473.html
Copyright © 2020-2023  润新知