【问题标题】:Open Binary File From Database C#从数据库 C# 打开二进制文件
【发布时间】:2012-02-17 20:19:05
【问题描述】:

我在 SQL Server 数据库中有 PDF 文件数据,列类型为 image(以前的数据库设计器不好)。我需要做的是将二进制数据读给客户端,以便他们可以将 PDF 直接下载到他们的计算机上。

到目前为止,我的代码如下:

SqlConnection con = new SqlConnection();
con.ConnectionString = "casIntranetConnectionString";

SqlCommand com = new SqlCommand("SELECT [File], [FileName] FROM [com].[catalog1] WHERE [FileName] = @filename");
com.Connection = con;
com.Parameters.AddWithValue("filename", Request.QueryString["filename"]);

con.Open();

SqlDataReader reader = com.ExecuteReader();

if (reader.Read())
{
    Response.Clear();
    Response.AddHeader("Content-Type", "application/pdf");
    Response.AddHeader("Content-Disposition", "inline; filename=" + Request.QueryString["filename"] + ".pdf");
}

我假设我需要读者读出字节,但那是我真的不知道我在做什么的地方。有什么建议吗?

谢谢!

【问题讨论】:

  • 在您做任何事情之前,您是否有理由在 2012 年使用 ADO.NET 手动执行此操作?
  • @TimothyP 是否愿意提出合适的替代方案?
  • 我建议你看一下实体框架等技术,虽然我当然无法告诉你它是否适合你的项目,我认为它“可能”是。它使您可以专注于什么,而不是如何。请不要冒犯,非故意的
  • 能不能直接将二进制文件注入媒体播放器,这样就不用下载了,只是即时播放文件?

标签: c# asp.net sql-server database pdf


【解决方案1】:

我相信这应该可行:

if(reader.Read())
{
    Byte[] pdfData = (byte[])reader.GetValue(0);;
    Response.Buffer = true;
    Response.ContentType = "application/PDF";
    Response.BinaryWrite(pdfData);
}

【讨论】:

    【解决方案2】:

    您可以使用 HttpResponse BinaryWrite method:

    var bytes = reader.GetSqlBytes(index);
    Response.BinaryWrite(bytes.Value);
    

    顺便说一句,请考虑分离职责,您有一个方法负责访问数据库并写入响应。这将导致未来的维护问题。请参阅描述 SOLID 原则的 here for a useful blog post。如果您的代码 sn-p 是人为设计的,我们深表歉意,但万一其他人偶然发现这个问题,我想包含一个“但不要这样做”免责声明!

    【讨论】:

      【解决方案3】:

      如果您想避免heap fragmentation(尤其是使用服务器端代码),从而避免分配大字节数组,您可以进行流式处理,如下所示:

              using (SqlConnection cnx = new SqlConnection(@"your connection string"))
              {
                  cnx.Open();
                  using (SqlCommand cmd = cnx.CreateCommand())
                  {
                      cmd.CommandText = "SELECT [File] FROM [com].[catalog1] WHERE [FileName] = @filename";
                      cmd.Parameters.AddWithValue("filename", Request.QueryString["filename"]);
      
                      // sequential access is used for raw access
                      using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
                      {
                          if (reader.Read())
                          {
                              // must be lower than 85K (to avoid Large Object Heap fragmentation)
                              byte[] chunk = new byte[0x10000]; 
                              long read;
                              long offset = 0;
                              do
                              {
                                  read = reader.GetBytes(0, offset, chunk, 0, chunk.Length);
                                  if (read > 0)
                                  {
                                      Response.OutputStream.Write(chunk, 0, (int)read);
                                      offset += read;
                                  }
                              }
                              while (read > 0);
                              Response.AddHeader("Content-Type", "application/pdf");
                              Response.AddHeader("Content-Disposition", "inline; filename=" + Request.QueryString["filename"] + ".pdf");                        
                          }
                      }
                  }
              }
      

      如果您经常提供相同的文件,那么最好将此文件直接写入服务器上的某个缓存目录,然后将其重新用于后续请求,使用Response.TransmitFile API,这是最好的性能(如果可能,使用内核模式)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-19
        • 1970-01-01
        • 2011-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多