Не удается извлечь переменные данные из MSSQL


Предыстория

Среда разработки:

PHP 7.0.3 с Apache 2.4.16 в Windows 10 x64

Стандарт SQL Server 2014

У сервера включен поток файлов в соответствующих столбцах файлов.

Попытался установить драйвер sqlsvr, но не удалось из-за отсутствия поддержки PHP7

Доступ к SQL server из ODBC с помощью драйвера SQL Server

PHP-код для вставки данных изображения в MSSQL

$link = @new \PDO("odbc:Driver={SQL Server};Server=$server;Database=$db", $user, $password);
$stmt = $link->prepare("INSERT INTO [Attachment] (AttID, Seq , ModuleCde, AppID, StaffID , FileName , [File]) VALUES ( NEWID() , ? , ? , ? , ? , ? , ? )");
$stmt->bindValue(1,$_POST["Seq"],PDO::PARAM_INT);
$stmt->bindValue(2,$_POST["ModuleCde"],PDO::PARAM_STR);
$stmt->bindValue(3,$_POST["AppID"],PDO::PARAM_STR);
$stmt->bindValue(4,$_SESSION["StaffID"],PDO::PARAM_STR);
$stmt->bindValue(5,$_FILES["file"]["name"][$_POST["Seq"]],PDO::PARAM_STR);
$stmt->bindValue(6,file_get_contents($_FILES["file"]["tmp_name"][$_POST["Seq"]]),PDO::PARAM_STR);
$stmt->execute();

PHP-код для сохранения данные изображений из MSSQL

$link = @new \PDO("odbc:Driver={SQL Server};Server=$server;Database=$db", $user, $password);
$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size] , CONVERT(NVARCHAR(MAX),[File],2) AS [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");
$stmt->bindValue(1,$_GET["ModuleCde"],PDO::PARAM_STR);
$stmt->bindValue(2,$_GET["AppID"],PDO::PARAM_STR);
$stmt->bindValue(3,$_GET["Seq"],PDO::PARAM_STR);
$stmt->bindValue(4,$_SESSION["StaffID"],PDO::PARAM_STR);
$stmt->execute();
$stmt->bindColumn(2,$img,PDO::PARAM_LOB, 0);
$stmt->fetch(PDO::FETCH_ASSOC);
file_put_contents( "file" , $img );

Файл успешно загружен на сервер SQL. Открытие каталога DATA сервера SQL, все загруженные файлы и могут быть открыты с помощью Paint.

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

Опробованный метод

fwrite( fopen("file","w+") , strtolower("0x".str_replace("\0","",$img)) );

А также метод, указанный в этой ссылке.

Php с MSSQL отображает необработанные данные из varbinary поле

Но обоим не повезло, файл также, похоже, был поврежден.

Любая помощь приветствуется.

Редактировать 2016-02-25

Изменил инструкцию SQL следующим образом, но выходной файл все еще поврежден.

 $link->prepare("SELECT DATALENGTH([File]) AS [Size] , [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");

Сейчас я пытаюсь изменить другой драйвер ODBC SQL server, чтобы проверить, может ли файл успешно выводиться.

Редактировать 2016-08-09

С обновленным драйвером MSSQL PDO для PHP 7. Все работало снова с очарованием.

Теперь нам больше не нужно convert использовать переменные данные с помощью этого нового драйвера.

Ссылка на Ссылку

Author: Community, 2016-02-24

3 answers

При вставке в таблицы, содержащие переменные, выбор типа данных очень важен для PHP PDO.

PDO::PARAM_LOB вместо этого следует использовать PDO::PARAM_STR для столбцов файла

Чтобы убедиться, что DB вывел правильный файл через драйвер, преобразуйте поле VARBINARY(MAX) в шестнадцатеричную строку и передайте ее PHP, обычно используя этот метод CONVERT(VARCHAR(MAX),[FileColumn],2)

Преобразование столбца в VARCHAR(MAX) вместо NVARCHAR(MAX), потому что шестнадцатеричные строки не нуждаются в поддержке Юникода и оставляют простой шестнадцатеричный строка.

Затем шестнадцатеричные строки могут быть эффективно преобразованы обратно из шестнадцатеричных данных в двоичные с помощью функции PHP hex2bin().

Решение

$link = @new \PDO("odbc:Driver={SQL Server};Server=$server;Database=$db", $user, $password);
$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size] , CONVERT(VARCHAR(MAX),[File],2) AS [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");
$stmt->bindValue(1,$_GET["ModuleCde"],PDO::PARAM_STR);
$stmt->bindValue(2,$_GET["AppID"],PDO::PARAM_STR);
$stmt->bindValue(3,$_GET["Seq"],PDO::PARAM_STR);
$stmt->bindValue(4,$_SESSION["StaffID"],PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
file_put_contents( "file" , hex2bin($result["File"]) );

Дополнительная Информация

При выборе столбца varbinary из SQL Server Native Client 11.0 и ODBC Driver 11 for SQL Server, ни преобразовывая столбец в varchar, ни нет, PHP выводит поврежденный двоичный результат, который нежелателен. Но драйвер SQL Server успешно возвращает мне шестнадцатеричную строку, когда я преобразую столбец в VARCHAR(MAX). Я подозреваю это действие является ошибкой или проблемой с драйвером.

 4
Author: MiKeNeko, 2016-02-26 15:58:11

Если вы храните двоичные данные, не преобразуйте их в NVARCHAR() при выборе - попробуйте удалить ПРЕОБРАЗОВАНИЕ() из этого:

$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size] , CONVERT(NVARCHAR(MAX),[File],2) AS [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");

Будь таким:

$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size], [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");

Вы также хотите убедиться, что ваш столбец VARBINARY(MAX).

При вставке ваших данных, я думаю, вам нужно использовать SQLSRV_ENCODING_BINARY (вместо PDO::PARAM_STR)

 3
Author: Robert Paulsen, 2016-02-24 16:42:12
  1. Установить сервер MSSQL
  2. Установите драйвер ODBC в соответствии с версией ОС и версией SQL Server, например, 64-разрядная версия win 10 и SQL server 12 требуется драйвер odbc 11

    Скачать по этой ссылке

  3. pdo_sqlsrv_.dll файлы загружаются в соответствии с версией php и вставляются в каталог php/ext и открываются из части расширений php.ini. например, в моем случае установите версию xampp 3.2.2, которая включает php 7.08, для этого я загружаю pdo_sqlsrv_7_ts.dll и установил согласно вышеупомянутому упоминанию в пункте 3.

    Скачать по этой ссылке:

  4. Задайте параметр подключения к базе данных в PHP-файле, например

    $conn =новый PDO("sqlsrv: сервер=127.0.0.1,1433; База данных= тест", "", "");
    $conn->Установить атрибут (PDO::ATTR_ERRMODE, PDO::ИСКЛЮЧЕНИЕ ERRMODE_EXCEPTION);

 -1
Author: Muhammad Sulman, 2017-05-02 11:04:08