Открыть двоичный файл из базы данных C # - PullRequest
4 голосов
/ 24 января 2012

У меня есть данные файла PDF в базе данных SQL Server, в столбце типа 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");
}

Я предполагаю, что мне понадобится считыватель, чтобы считывать байты, но на самом деле я этого не делаюзнаю, что я делаюЕсть предложения?

Спасибо!

Ответы [ 3 ]

5 голосов
/ 24 января 2012

Вы можете использовать метод HttpResponse BinaryWrite :

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

Кроме того, рассмотрите возможность разделения обязанностей, у вас есть метод, который отвечает за доступ к базе данных и запись вответ.Это приведет к проблемам с обслуживанием в будущем.См. здесь для полезного сообщения в блоге , описывающего принципы SOLID.Приносим извинения, если ваш фрагмент кода был придуман, но в случае, если кто-то еще наткнется на этот вопрос, решил, что я бы добавил отказ от ответственности, но не делайте этого!

3 голосов
/ 24 января 2012

Если вы хотите избежать фрагментации кучи (особенно с серверным кодом) и, таким образом, избежать выделения огромных байтовых массивов, вы можете выполнять потоковую передачу, что-то вроде этого:

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

И если вы часто обслуживаете один и тот же файл, то лучше записать этот файл непосредственно в какой-либо каталог Cache на сервере, а затем повторно использовать его для последующего запроса с помощью Response.TransmitFile API, который является лучшим с точки зрения производительности (если возможно, использует режим ядра).

1 голос
/ 24 января 2012

Я считаю, что это должно работать:

if(reader.Read())
{
    Byte[] pdfData = (byte[])reader.GetValue(0);;
    Response.Buffer = true;
    Response.ContentType = "application/PDF";
    Response.BinaryWrite(pdfData);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...