【问题标题】:How to access files stored in SQL Server's FileTable?如何访问存储在 SQL Server FileTable 中的文件?
【发布时间】:2017-06-01 12:49:17
【问题描述】:

据我所知,SQL Server 自 2012 版以来有一个新功能,FileTable。它允许我们将文件存储在文件系统中并从 T-SQL 中使用它们。

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

一般来说,我不知道如何访问存储在文件表中的文件。假设我有 asp.net MVC 应用程序,并且我在网页上的 img 标签中显示了很多图像。我想将这些图像存储在 Filetable 中,并将它们作为文件系统中的文件进行访问。但我不知道这些文件存储在哪里以及如何将它们用作文件。现在我的图像存储在文件夹图像的网络应用程序目录中,我写了这样的东西:

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

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

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

【问题讨论】:

    标签: sql sql-server asp.net-mvc filetable


    【解决方案1】:

    我认为您仍然不需要这个,无论如何我会为其他感兴趣的人发布我的答案。 首先,文件表仍然是一个表,因此,如果您想从中访问数据,您需要使用 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" />
    

    希望这会有所帮助! 如果您想知道文件表的架构,请参阅 here

    【讨论】:

      【解决方案2】:

      我假设 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 服务器,除非您将图像存储在浏览器可以的其他位置正确缓存(我的示例没有这样做)-如果您将它们存储在其他地方以在浏览器中呈现,您最好将它们存储在那里(一旦它们被复制,这些图像将不会具有事务一致性无论如何到其他驱动器/磁盘/位置)。

      说了这么多,下面是一个示例,说明如何使用 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 个事务范围 - 此代码无法处理)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多