【问题标题】:How to store the file in the database?如何将文件存储在数据库中?
【发布时间】:2010-03-15 05:42:39
【问题描述】:

如何将用户上传的文件保存到数据库中?我想将文件存储在数据库中,我们该怎么做?在后端我使用 sql 和 c#.net 应用程序。

【问题讨论】:

  • sql 在 SQL Server 中?? SQL 只是查询语言......不是产品/数据库系统,真的......
  • 我们的任何解决方案是否对您有所帮助或您仍需要更多帮助?

标签: c# .net winforms sql-server-2005


【解决方案1】:

此解决方案适用于 SQL SERVER 2005/2008。

您必须创建以VARBINARY(MAX) 作为列之一的表。在我的例子中,我创建了表 Raporty,其中 RaportPlik 列是 VARBINARY(MAX) 列。

您可以根据需要修改以下几个支持功能:

    public static void databaseFilePut(string varFilePath) {
        byte[] file;
        using (var stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read)) {
            using (var reader = new BinaryReader(stream)) {
                file = reader.ReadBytes((int) stream.Length);

            }

        }
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlWrite = new SqlCommand("INSERT INTO Raporty (RaportPlik) Values(@File)", varConnection)) {
            sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file;
            sqlWrite.ExecuteNonQuery();
        }
    }
    public static void databaseFileRead(string varID, string varPathToNewLocation) {
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) {
            sqlQuery.Parameters.AddWithValue("@varID", varID);
            using (var sqlQueryResult = sqlQuery.ExecuteReader())
                if (sqlQueryResult != null) {
                    sqlQueryResult.Read();
                    var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))];
                    sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length);
                    using (var fs = new FileStream(varPathToNewLocation, FileMode.Create, FileAccess.Write)) fs.Write(blob, 0, blob.Length);
                }
        }
    }
    public static MemoryStream databaseFileRead(string varID) {
        MemoryStream memoryStream = new MemoryStream();
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) {
            sqlQuery.Parameters.AddWithValue("@varID", varID);
            using (var sqlQueryResult = sqlQuery.ExecuteReader())
                if (sqlQueryResult != null) {
                    sqlQueryResult.Read();
                    var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))];
                    sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length);
                    //using (var fs = new MemoryStream(memoryStream, FileMode.Create, FileAccess.Write)) {
                    memoryStream.Write(blob, 0, blob.Length);
                    //}
                }
        }
        return memoryStream;
    }

第一种方法是从驱动器中将文件放入数据库,第二种方法是获取文件并将其保存在驱动器上,第三种方法是从数据库中获取文件并将其作为MemoryStream,以便您可以使用它来做一些其他的事情然后把它写到驱动器上。

第4种方法是将MemoryStream放入数据库:

public static int databaseFilePut(MemoryStream fileToPut) {
        int varID = 0;
        byte[] file = fileToPut.ToArray();
        const string preparedCommand = @"
                    INSERT INTO [dbo].[Raporty]
                               ([RaportPlik])
                         VALUES
                               (@File)
                        SELECT [RaportID] FROM [dbo].[Raporty]
            WHERE [RaportID] = SCOPE_IDENTITY()
                    ";
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) {
            sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file;

            using (var sqlWriteQuery = sqlWrite.ExecuteReader())
                while (sqlWriteQuery != null && sqlWriteQuery.Read()) {
                    varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0;
                }
        }
        return varID;
    }

【讨论】:

    【解决方案2】:

    MS SQL Server 2008(及以上,我猜)提供FileStream data type。只需 Google (或 Bing 它,随便 :-)),我想你会找到你需要的。

    【讨论】:

      【解决方案3】:

      假设 SQL 2005 或更高版本,我将使用 VarBinary(MAX) 字段。将上传的文件作为 byte[] 传递给插入语句。据微软称,自 SQL 2005 起,在数据库中存储大量数据(文件和图像)不再会在很大程度上降低性能。

      例如:

      public void SaveFileToDB(string description, byte[] file)
      {
          using (SqlConnection con = new SqlConnection(conStr)
          {
              con.Open();
              using (SqlCommand cmd = con.CreateCommand())
              {
                  cmd.Parameters.Add("@Description", SqlDbType.VarChar, description);
                  cmd.Parameters.Add("@File", SqlDbType.VarBinary, file);
                  cmd.CommandText = "UploadedFileUpdate";
                  cmd.CommandType = CommandType.StoredProcedure;
                  cmd.ExecuteNonQuery();
              }
          }
      }
      

      如果您有 SQL 2008,请参阅 Ron Klein 的建议。

      【讨论】:

      • 我仍然不会推荐它,除非 1) 您的文件数量相当少且文件大小很小,或者 2) 您拥有支持解决方案扩展的基础架构。我曾在两家商店工作,我的第一份工作是弄清楚他们如何移动由于在数据库中存储文件的做法而失去控制的 大量 数据库,尤其是当那些文件高度冗余(由 MD5 校验和确定)
      • @GrayWizardx 同意,但我假设 Harikrishna 已经决定存储在数据库中。在某些情况下(例如共享主机),您无法写入文件系统。
      • @GrayWizardx:最大约 1 MB 大小,将文件存储在数据库中最好是将其存储在文件系统中。此外,将 VARBINARY(MAX) 列放入单独的表中,甚至可能是单独的文件组,可以帮助控制事情。
      • 我猜罗伯茨解决方案是适合这种情况的解决方案@Marc 好点
      • @GrayWizardx:我没有 - Microsoft Research 有 - 请参阅“To Blob or Not To Blob”:research.microsoft.com/apps/pubs/default.aspx?id=64525
      【解决方案4】:

      降低数据库大小的一种解决方案是将文件的位置存储在服务器上。 IE 一个文件路径。

      但是,如果您想移动文件,则必须创建一个管理员。

      【讨论】:

        【解决方案5】:

        您可以使用 blob 字段类型。当您从 StreamReader 读取文件时,将其转换为字节数组,然后将其插入到 blob 字段中。

        当你想读取它时的相反过程,将 blob 作为字节数组获取,将其读入流读取器并将其写入响应缓冲区。

        【讨论】:

          猜你喜欢
          • 2011-07-10
          • 2014-07-18
          • 1970-01-01
          • 2013-09-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多