Сохранить файл XLSM в столбец базы данных и извлечь?

Ранее реализованный код принимает файл xls и сохраняет его в столбце таблицы, используя поток. Я использую тот же метод, но единственное изменение заключается в том, что сохраненный файл представляет собой файл типа xlsm или xlsx, который он сохраняет в столбце в таблице. база данных

Когда я пытаюсь получить содержимое из базы данных и выбрасываю сохраненный файл xlsm или файл xlsx, я получаю сообщение об ошибке «Файл Excel обнаружил нечитаемое содержимое. Вы хотите восстановить содержимое этой рабочей книги?»

Вот код для сохранения файла xlsm или xlsx

System.IO.Stream filestream = System.IO.File.Open(file, System.IO.FileMode.Open);
int fileLength = (int)filestream.Length;
byte[] input = new byte[fileLength];
filestream.Read(input, 0, fileLength);
string Sql = "insert into upload values(@contents)";
con.Open();
System.Data.SqlClient.SqlCommand c = new System.Data.SqlClient.SqlCommand(Sql, con);
c.Parameters.Add("@contents", System.Data.SqlDbType.Binary);
c.Parameters["@contents"].Value = input;
c.ExecuteNonQuery();

Чтобы получить и отправить пользователю

SqlCommand comm = new SqlCommand("select contents from upload order by id desc", con);
SqlDataReader reader = comm.ExecuteReader();
int bufferSize = 32768;                   
        byte[] outbyte = new byte[bufferSize];  
        long retval;                           
        long startIndex = 0;                    
        startIndex = 0;
        retval = reader.GetBytes(0, startIndex, outbyte, 0, bufferSize);
        while (retval > 0)
        {
            System.Web.HttpContext.Current.Response.BinaryWrite(outbyte);
            startIndex += bufferSize;
            if (retval == bufferSize)
            {
                retval = reader.GetBytes(2, startIndex, outbyte, 0, bufferSize);
            }
            else
            {
                retval = 0;
            }
        }

person Community    schedule 09.06.2009    source источник
comment
Не могли бы вы показать нам какой-нибудь код, так как из вашего описания невозможно сказать, в чем может быть проблема.   -  person samjudson    schedule 09.06.2009
comment
Согласен, похоже, вы неправильно отправили поток на сервер. Наиболее распространенная причина — не учитывать должным образом возвращаемое значение stream.Read(...)   -  person Marc Gravell    schedule 09.06.2009
comment
Извините, код выглядит плохо, когда он был опубликован в качестве комментария. Теперь я отредактировал вопрос с кодом. Спасибо.   -  person    schedule 09.06.2009


Ответы (2)


Несколько вещей кажутся мне возможными.

Во-первых, вы не звоните reader.Read().

Во-вторых, нет необходимости в проверке на retval == bufferSize — достаточно снова вызвать GetBytes, и он вернет 0, если из поля не было прочитано ни одного байта.

В-третьих, когда вы пишете в HttpResponse, вам нужно убедиться, что вы вызываете Response.Clear() перед записью байтов в вывод и Response.End() после записи файла в ответ.

Еще одна вещь, которую стоит попробовать, — это сохранить файл на жесткий диск и сравнить его с оригиналом. Это тот же размер? Если он больше, то вы записываете в файл слишком много информации (см. предыдущие комментарии о HttpResponse). Если он меньше, значит, вы пишете недостаточно и, скорее всего, выходите из цикла слишком рано (см. комментарий к retval).

person samjudson    schedule 09.06.2009
comment
Привет, спасибо за ваш ответ, упомянутые пункты 1. reader.Read() используется в выражении if, если оно истинно, то оно переходит к методу чтения двоичных данных. 2. Я тоже использовал Response.Clear 3. Я удалил дополнительный код, который вы упоминаете, не требуется, файл успешно загружается, но не открывается, я получаю ту же ошибку. Это потому, что новый файл MS Excel в формате xlsx или xlsm содержит несколько файлов xml? - person ; 09.06.2009
comment
Расширение файла не должно иметь значения для кода. Если он отлично работал для .xls, но теперь не работает для .xlsx, то, возможно, это потому, что Excel был более снисходителен к формату файла .xls, хотя я в этом сомневаюсь. Вы не отвечаете на вопрос о размере файла. Если вы правильно читаете и записываете файл, он должен быть точно таким же, когда вы сохраняете его на диск. - person samjudson; 09.06.2009

Я не мог не заметить количество мест, где ваш код не смог обернуть IDisposable в блок using, например:

using (SqlConnection con = new SqlConnection(connectionString))
{
    byte[] input;
    using (System.IO.Stream filestream = System.IO.File.Open(file, System.IO.FileMode.Open))
    {
        int fileLength = (int)filestream.Length;
        input = new byte[fileLength];
        filestream.Read(input, 0, fileLength);
    }
    const string Sql = "insert into upload values(@contents)";
    con.Open();
    using (System.Data.SqlClient.SqlCommand c = new System.Data.SqlClient.SqlCommand(Sql, con))
    {
        c.Parameters.Add("@contents", System.Data.SqlDbType.Binary);
        c.Parameters["@contents"].Value = input;
        c.ExecuteNonQuery();
    }

    using (SqlCommand comm = new SqlCommand("select contents from upload order by id desc", con))
    {
        using (SqlDataReader reader = comm.ExecuteReader())
        {
            int bufferSize = 32768;
            byte[] outbyte = new byte[bufferSize];
            long retval;
            long startIndex = 0;
            startIndex = 0;
            retval = reader.GetBytes(0, startIndex, outbyte, 0, bufferSize);
            while (retval > 0)
            {
                System.Web.HttpContext.Current.Response.BinaryWrite(outbyte);
                startIndex += bufferSize;
                if (retval == bufferSize)
                {
                    retval = reader.GetBytes(2, startIndex, outbyte, 0, bufferSize);
                }
                else
                {
                    retval = 0;
                }
            }
        }
    }
}
person John Saunders    schedule 17.07.2009