繁体   English   中英

如何访问存储在SQL Server FileTable中的文件?

[英]How to access files stored in SQL Server's FileTable?

据我所知,自2012版以来的SQL Server具有一项新功能FileTable 它使我们可以将文件存储在文件系统中,并可以通过T-SQL使用它们。

我正在尝试使用此功能,我不知道如何正确执行。

通常,我不知道如何访问文件表中存储的文件。 假设我有asp.net MVC应用程序,并且在网页上的img标签中显示了很多图像。 我想将这些图像存储在Filetable中,并从文件系统中以文件形式访问它们。 但是我不知道这些文件存储在哪里以及如何将它们用作文件。 现在,我的图像存储在Web应用程序目录中的文件夹图像中,我编写如下内容:

<img src='/images/mypicture.png' />

如果我将图像移动到文件表,应该在src中写什么?

<img src='path-toimage-in-filetable' />

我假设FileTable实际上是指FileStream。 关于此的一些注意事项:

  1. 如果您的文件实际上是文件,则最好使用此功能
  2. 文件平均应大于1mb-尽管此规则可能会有例外,但是如果文件平均小于1mb,则最好使用VARBINARY(MAX)XML数据类型。 如果图像平均很小(只有几个KB),请考虑使用VARBINARY(MAX)列。
  3. 访问这些文件将需要一个打开的事务,并且已为FILESTREAM正确配置了数据库
  4. 通过告诉SQL Server您要直接访问文件,可以绕过常规SQL引擎/数据库文件的数据访问方法,可以获得一些显着的优势,但是,这并不意味着直接访问文件系统上的文件并且尝试这样做可以破坏SQL对这些文件的管理(事务一致性,跟踪,锁定等)。
  5. 如果您确实需要SQL,则很有可能通过使用CDN并在表中存储图像URL来更好地满足您的用例。 可以使用FILESTREAM来执行此操作(有关一种实现,请参见下面的代码示例),但是除非您将图像存储在浏览器可以正常缓存的其他位置,否则您将为每个请求重用SQL Server(我的示例不这样做)那)-如果您将它们存储在其他位置以在浏览器中呈现,则最好将它们存储在此处(这些图像一旦复制到其他驱动器/磁盘/位置,就不会具有事务一致性) )。

综上所述,这是一个如何使用ADO.NET访问FILESTREAM数据的示例:

public static string connectionString = ...; // get your connection string from encrypted config

// assumes your FILESTREAM data column is called Img in a table called ImageTable
const string sql = @"
    SELECT            
        Img.PathName(),
        GET_FILESTREAM_TRANSACTION_CONTEXT()
      FROM ImageTagble
      WHERE ImageId = @id";

public string RetreiveImage(int id)
{
    string serverPath;
    byte[] txnToken;
    string base64ImageData = null;
    using (var ts = new TransactionScope())
    {
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;
                using (SqlDataReader rdr = cmd.ExecuteReader())
                {
                    rdr.Read();
                    serverPath = rdr.GetSqlString(0).Value;
                    txnToken = rdr.GetSqlBinary(1).Value;
                }
            }
            using (var sfs = new SqlFileStream(serverPath, txnToken, FileAccess.Read))
            {
            // sfs will now work basically like a FileStream.  You can either copy it locally or return it as a base64 encoded string
               using (var ms = new MemoryStream())
               {
                  sfs.CopyTo(ms);
                  base64ImageData = Convert.ToBase64String(ms.ToArray());
               }
            }
        }
        ts.Complete();
        // assume this is PNG image data, replace PNG with JPG etc. as appropraite.  Might store in table if it will vary...
        return "data:img/png;base64," + base64ImageData;
    }
}

显然,如果您要处理大量图像,这不是理想的方法-请勿尝试将SQL Server实例转换为应使用CDN的对象。...但是,如果您确实有其他有充分的理由,您应该尝试在单个请求/事务中获取尽可能多的图像(例如,如果您知道在一个页面上显示50张图像,请使用单个交易范围获取全部50张图像,而不使用50个交易范围-此代码将无法处理)。

我认为您仍然不需要这个,反正我会将答案发布给其他感兴趣的人。 首先,文件表仍然是表,因此,如果要从中访问数据,则需要使用Select SQL语句。 因此,您需要以下内容:

select name, file_stream from filetable_name 
where 
name = 'file_name',
file_type = 'file_extension'

只需在asp.net应用中执行这样的语句,然后获取结果并使用file_stream列即可获取存储文件的二进制数据。 如果要从HTML检索文件,则首先需要在控制器中创建一个操作,该操作将返回检索到的文件:

public ActionResult GetFile(){
..
return File(file.file_stream,file.file_type);
}

之后,在您的HTML标记中添加以下内容:

<img src="/controller/GetFile" />

希望这会有所帮助! 如果您想了解文件表的架构,请参见此处

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM