简体   繁体   English

从数据库C#打开二进制文件

[英]Open Binary File From Database C#

I have PDF file data in a SQL Server database, in the column type image (bad previous db designer). 我在SQL Server数据库中的列类型image (坏的以前的数据库设计器)中有PDF文件数据。 What I need to do is read that binary data out to the client, so that they could download the PDF directly to their computer. 我需要做的是将二进制数据读出到客户端,以便他们可以将PDF直接下载到他们的计算机上。

So far, my code is as follows: 到目前为止,我的代码如下:

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");
}

I'm assuming I'm going to need the reader to read out the bytes, but that's where I don't really know what I do. 我假设我需要读者读出字节,但这就是我不知道我在做什么的地方。 Any suggestions? 有什么建议么?

Thanks! 谢谢!

You can use the HttpResponse BinaryWrite method : 您可以使用HttpResponse BinaryWrite方法

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

As an aside, please consider separating responsibilities, you have a method which is responsible for accessing the database AND writing to the response. 顺便说一句,请考虑分离职责,您有一个负责访问数据库和写入响应的方法。 This will lead to maintenance problems in the future. 这将导致将来出现维护问题。 See here for a useful blog post describing SOLID principles. 请参阅此处以获取描述SOLID原则的有用博客文章 Apologies if your code snippet was contrived, but in case any one else stumbles across this question figured I'd include a "but don't do it like this" disclaimer! 抱歉,如果你的代码片段是人为的,但万一其他人偶然发现这个问题,我想包括一个“但不要这样做”的免责声明!

If you want to avoid heap fragmentation (especially with server-side code), and thus avoid allocating huge byte arrays, you can do streaming, something like this: 如果你想避免堆碎片 (特别是服务器端代码),从而避免分配巨大的字节数组,你可以做流式传输,如下所示:

        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");                        
                    }
                }
            }
        }

And if you serve the same file often, then it's better to write this file directly to some Cache directory on the server and then re-use it for subsequent request, with the Response.TransmitFile API which is the best in terms of performance (uses kernel mode if possible). 如果您经常提供相同的文件,那么最好将此文件直接写入服务器上的某个Cache目录,然后将其重新用于后续请求,使用Response.TransmitFile API,这是性能最佳的(使用)内核模式,如果可能)。

I believe that this should work: 我认为这应该有效:

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

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

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