【问题标题】:What is the quickest way to stream an image from a FILESTREAM in SQL to a browser?将图像从 SQL 中的 FILESTREAM 流式传输到浏览器的最快方法是什么?
【发布时间】:2009-06-06 01:08:43
【问题描述】:

我将图像存储在我的数据库中的 FILESTREAM 中,我正在尝试找出最好的解决方案是将该图像重新输出到网络浏览器中。

如果我自己管理文件系统上的文件,最快的方法就是:

Response.TransmitFile(pathToFile);

这不会在将文件传输回客户端(据我了解)之前将文件加载到内存中,因此既好又快。

我目前正在使用 Linq to SQL 来获取 FILESTREAM。这会将 FILESTREAM 作为 Binary 对象提供。

到目前为止,有这种非常丑陋的做法:

Response.WriteBinary(fileStreamBinary.ToArray());

不使用 Linq to SQL 并更直接地做事会更好吗?

我开始想知道为什么我首先要为 FILESTREAM 而烦恼,而不仅仅坚持自己管理文件。我敢肯定没有使用“潮流”这个词是有原因的!

【问题讨论】:

    标签: .net sql-server linq-to-sql filestream


    【解决方案1】:

    这不会在将文件传输回之前将文件加载到内存中 客户(据我所知),因此很好而且很快。

    正确,但记得将Response.BufferOutput设置为false,默认值为true。

    不使用 Linq to SQL 并更直接地做事会更好吗?

    如果您不想先将整个二进制内容加载到内存中,那么可以。这是an example,用于从数据库流式传输二进制数据(以及启用可恢复下载功能)。

    我开始想知道为什么我一开始就使用 FILESTREAM 并不仅仅坚持自己管理文件

    主要好处是具有事务支持和包含在数据库备份中的数据完整性,因此您不必担心数据库备份和文件系统备份之间的差异。缺点一直是性能,这是整个文件流功能试图克服的问题。尽管根据this document,如果它们平均小于 1mb,则实际上存储在数据库中比存储在文件系统中更快。

    在 Sql Server 2012 中,有一个名为 FileTables 的新功能基于对 FileStream 的支持。基本上它就像文件系统目录的数据库视图,添加到该目录的文件会自动添加到数据库 FileTable(是一个固定模式表,其中包含文件的 Filestream 二进制列,您可以从其他表链接到)。然后,这将允许您检索可以提供给 Response.TransmitFile(...) 函数的文件的路径,但仍然可以从 sql Filestream 支持中受益。

    【讨论】:

      【解决方案2】:

      那怎么样?

      byte[] buffer = new byte[bufferSize];
      int nBytes;
      while((nBytes = fileStreamBinary.Read(buffer, 0, bufferSize) != 0)
      {
          Response.OutputStream.Write(buffer, 0, nBytes);
      }
      

      这样你就永远不会将整个流加载到内存中

      【讨论】:

      • 嗯,也许我们在谈论不同的 Binary 对象类型 - Linq 返回一个没有 Read() 方法的 System.Data.Linq.Binary 对象:(
      • 对不起,我误解了你的代码示例,并认为 fileStreamBinary 是一个流......我不熟悉 System.Data.Linq.Binary,但它似乎是一次获取整个缓冲区,因此您无法避免将其加载到内存中。所以恐怕你觉得“丑陋”的代码是唯一的方法......
      • 看起来我在使用 FILESTREAM 时可能不得不绕过 Linq。似乎很愚蠢,因为 FILESTREAM 的全部意义在于允许超快速的直接从磁盘流式传输!
      • 您可以通过在 DataContext.Connection 上执行 SqlCommand 来实现,并使用 SqlDataReader.GetBytes 检索数据
      • @ThomasLevesque SqlFileStream 是指定用于读取使用 Filestream 支持存储的二进制数据的 SqlType。
      【解决方案3】:

      与 Thomas 提出的想法基本相同,但有点冗长。 应关闭缓冲并定期提交/刷新数据,以避免在将所有传入数据发送到客户端之前对其进行缓冲。

      我正在使用类似的代码从 数据库 -> WCF 服务(流式传输)-> 客户端(浏览器)

      对于较小的项目,这可能不是最好的方法,但对于传输来自某种流的内容很有用。

      Response.Clear();
      Response.ContentType = "application/pdf";
      Response.Buffer = false;
      
      var buffer = new byte[BufferSize];
      int bytesRead;
      while ((bytesRead = inputStream.Read(buffer, 0, BufferSize)) != 0)
      {
           if (!Response.IsClientConnected)
                break;
      
           Response.OutputStream.Write(buffer, 0, bytesRead);
           Response.Flush();
      }
      

      【讨论】:

        猜你喜欢
        • 2015-07-25
        • 2014-05-25
        • 2012-04-14
        • 2010-11-03
        • 1970-01-01
        • 2013-04-18
        • 2011-04-13
        • 1970-01-01
        • 2014-11-10
        相关资源
        最近更新 更多