如何将文件存储在数据库中?

时间:2010-03-15 05:42:39

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

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

5 个答案:

答案 0 :(得分:4)

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

您必须使用VARBINARY(MAX)创建表作为其中一列。在我的情况下,我创建了表Raporty,其中列RaportPlikVARBINARY(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;
    }

答案 1 :(得分:3)

假设SQL 2005或更高版本,我将使用VarBinary(MAX)字段。将上传的文件作为byte []传递给insert语句。据微软称,自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的建议。

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

但是,如果你想要移动文件,你必须成为一名经理。

答案 4 :(得分:0)

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

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