Не удается извлечь переменные данные из 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
использовать переменные данные с помощью этого нового драйвера.
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)
. Я подозреваю это действие является ошибкой или проблемой с драйвером.
Если вы храните двоичные данные, не преобразуйте их в 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
)
- Установить сервер MSSQL
-
Установите драйвер ODBC в соответствии с версией ОС и версией SQL Server, например, 64-разрядная версия win 10 и SQL server 12 требуется драйвер odbc 11
Скачать по этой ссылке
-
pdo_sqlsrv_.dll
файлы загружаются в соответствии с версией php и вставляются в каталог php/ext и открываются из части расширений php.ini. например, в моем случае установите версию xampp 3.2.2, которая включает php 7.08, для этого я загружаю pdo_sqlsrv_7_ts.dll и установил согласно вышеупомянутому упоминанию в пункте 3.Скачать по этой ссылке:
-
Задайте параметр подключения к базе данных в PHP-файле, например
$conn =новый PDO("sqlsrv: сервер=127.0.0.1,1433; База данных= тест", "", "");
$conn->Установить атрибут (PDO::ATTR_ERRMODE, PDO::ИСКЛЮЧЕНИЕ ERRMODE_EXCEPTION);