MSSQL VARBINARY в PDF с использованием PHP

Используя специальное приложение DevExpress, наши пользователи загружают PDF-файлы, которые сохраняются в столбце VARBINARY(MAX) в базе данных MSSQL 2008.

У меня есть LAMP box, который успешно подключается к этой базе данных с помощью драйвера FreeTDS.

Я могу извлекать другие типы информации (изображения, хранящиеся в виде больших двоичных объектов, дат, строк и т. д.), но когда я пытаюсь обслуживать PDF-файлы, они каким-то образом повреждаются.

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

До и после

PHP, который я использую для обслуживания файла:

<?php
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public"); 
header("Content-Description: File Transfer");
header("Content-type:application/pdf");
header("Content-Disposition:attachment;filename=" . $arr[0]['FileName']);
header("Content-Transfer-Encoding: binary");
echo $arr[0]['FileContent'];

С#, используемый для сохранения файла в БД:

public void LoadFromStream(string fileName, Stream stream)
{
  Guard.ArgumentNotNull(stream, "stream");
  Guard.ArgumentNotNullOrEmpty(fileName, "fileName");
  FileName = fileName;
  byte[] bytes = new byte[stream.Length];
  stream.Read(bytes, 0, bytes.Length);
  Content = bytes;
}

public void SaveToStream(Stream stream)
{
  if (string.IsNullOrEmpty(FileName))
  {
    throw new InvalidOperationException();
  }
  stream.Write(Content, 0, Size);
  stream.Flush();
}

public byte[] Content
{
  get { return GetDelayedPropertyValue<byte[]>("Content"); }
  set
  {
    int oldSize = size;
    if (value != null)
    {
      size = value.Length;
    }
    else
    {
      size = 0;
    }
    SetDelayedPropertyValue<byte[]>("Content", value);
    OnChanged("Size", oldSize, size);
  }
}

Я прочитал почти все статьи, которые смог найти, выполнив поиск «php varbinary, php output stream, php varbinary stream, varbinary encoding». Помощь или предложения очень ценятся!


person darronz    schedule 16.05.2012    source источник
comment
Похоже, загруженный файл содержит менее половины байт исходного файла. Как массив байтов выглядит в базе данных до того, как вы вернете его обратно в код PHP?   -  person Jamie Dixon    schedule 16.05.2012
comment
@JamieDixon, БД содержит 5414 символов. Здесь находится zip-архив, содержащий PDF-файлы до и после, а также текстовый файл с содержимым базы данных. Я намеренно создал пустые PDF-файлы, чтобы уменьшить размер файла.   -  person darronz    schedule 16.05.2012


Ответы (1)


С этим есть пара проблем.

Во-первых, данные, хранящиеся в базе данных, имеют шестнадцатеричный формат, поэтому вам нужно будет преобразовать их обратно в массив байтов в вашем PHP-коде, прежде чем предоставлять их пользователю.

Во-вторых, шестнадцатеричное представление, которое у вас есть в базе данных, кажется неверным для используемого вами PDF-файла.

Когда я преобразовал PDF-файл из байтового массива в шестнадцатеричное представление, я получил совершенно другую шестнадцатеричную строку, которая при преобразовании обратно в байтовый массив работает нормально.

person Jamie Dixon    schedule 16.05.2012
comment
Я принимаю это как правильный ответ, указывающий, что массив байтов содержит около половины байтов исходного файла. Возвращаясь к разработчикам DevExpress, выяснилось, что они используют CompressionConverter при управлении потоком. - person darronz; 16.05.2012