сохранить изображение в базе данных mssql как varbinary (max) без конвертации - PullRequest
0 голосов
/ 04 сентября 2018

Программное обеспечение ERP нашей компании хранит фотографии сотрудников в виде блобов в нашей базе данных MSSQL.

Моя задача состоит в том, чтобы найти способ хранения изображений в одной и той же таблице базы данных таким образом, чтобы их можно было отображать в программе ERP.

Попробуйте # 1

$content = file_get_contents('my_path\my_file.png');
INSERT INTO my_table VALUES (CAST('{$data}' AS varbinary(max)))

выдает эту ошибку:

SQLSTATE[IMSSP]: An error occurred translating the query string to UTF-16

Проверка моей кодировки:

mb_internal_encoding() - это UTF-8, однако
mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true) - это ISO-8859-1.

Попробуйте # 2
Преобразование кодировки содержимого в UTF-8:

$content = file_get_contents('my_path\my_file.png');
$data = iconv('', 'UTF-8//TRANSLIT', $content);
INSERT INTO my_table VALUES (CAST('{$data}' AS varbinary(max)))

РАБОТАЕТ для маленького черного квадратного изображения.
Попытка сделать это на маленьком красном квадратном изображении, однако, приводит к этой ошибке:

iconv(): Detected an illegal character in input string

Попробуйте # 3 (a / b / c)
Множество способов перевести или просто избавиться от этих нелегальных символов:

$data = iconv('', 'UTF-8//IGNORE', $content);
$data = base64_encode($data);
$data = mb_convert_encoding($data, 'UTF-8', 'ISO-8859-1');

Разрешить из них позволяет нам сохранять в базе данных, но это не помогает нам, потому что данные изменяются и программа ERP не может их прочитать.

Другие опции
Мы думали о
BulkColumn FROM OPENROWSET(Bulk‘ C: \temp\ nextup.jpg’, SINGLE_BLOB) AS BLOB
способ вставить файл в базу данных, но отклонил его, поскольку он требует, чтобы мы сначала сохранили файл на диске сервера базы данных, что мы не хотим делать.

Вопрос
Тогда остается вопрос: как загрузить загруженный файл изображения в наше поле UTF-16 без изменения содержимого?

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Этот простой пример демонстрирует, как вставить изображение в столбец varbinary(max) в SQL Server, а затем вернуть изображение и сохранить его на диск. Пример использует Драйвер PHP для SQL Server . В вашем случае хорошо использовать параметризованные запросы.

Таблица:

CREATE TABLE [dbo].[ImageTable] (
    [ImageData] varbinary(max) NULL
)

PHP:

<?php
# Connection
$server = 'server\instance,port';
$database = 'database';
$uid = 'user';
$pwd = 'password';
$cinfo = array(
    "Database" => $database,
    "UID" => $uid,
    "PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if( $conn === false )
{
    echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
    exit;
}

# Insert image using CONVERT()
$image = file_get_contents('image.jpg');
$sql = "INSERT INTO ImageTable (ImageData) VALUES (CONVERT(varbinary(max), ?))";
$params = array(
    array($image, SQLSRV_PARAM_IN)
);
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
    echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
    exit;
}

# Insert image using SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY)
$image = file_get_contents('image.jpg');
$sql = "INSERT INTO ImageTable (ImageData) VALUES (?)";
$params = array(
    array($image, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY))
);
if ($stmt === false) {
    echo "Error insert (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
    exit;
}

# Get image from first row and save it again on disk. 
$sql = "SELECT ImageData FROM ImageTable";
$stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) {
    echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
    exit;
}
if (sqlsrv_fetch($stmt)) {
    $image = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
    file_put_contents('image2.jpg', $image);
}

# End
echo 'Image inserted.'
?>
0 голосов
/ 14 сентября 2018

Laravel использует класс PDO для доступа к базе данных. По умолчанию он интерпретирует все атрибуты как строки, что приводит к ошибке преобразования. Один из способов исправить это - дать PDO команду ожидать двоичный файл, используя setAttribute ():

$pdo = \DB::connection('my_conn')->getPdo();
$sql = "INSERT INTO my_table VALUES (CONVERT(varbinary(max), ?));"
$stmt = $pdo->prepare($sql);

$stmt->setAttribute(\PDO::SQLSRV_ATTR_ENCODING, \PDO::SQLSRV_ENCODING_BINARY);

$stmt->bindValue(1, file_get_contents($file);
$stmt->execute();

Спасибо @zhorov за то, что поставили меня на правильный путь. Просто добавил этот ответ, чтобы использовать больше Laravel.

0 голосов
/ 04 сентября 2018

Просто мысль.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >

Также вы можете попробовать выполнить этот запрос сразу после подключения к базе данных:

"SET NAMES 'utf8'"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...