Intereting Posts
Как получить текущего пользователя Joomla с внешним скриптом PHP Как проверить, является ли сеанс PHP пустым? Как получить несколько полей Multi Values как я могу заставить мой локоть ждать несколько секунд до соскабливания? Автоматическое разрешение Laravel ioc – работает от контроллера, но не от пользовательского класса Надежно предоставить уникальный секретный код победителю флеш-игры? Интеграция php и R Обновление данных полей базы данных MySQL с помощью HTML-формы и PHP PHP Twitter Hashtag Search не показывает результаты в синтаксическом анализе, но данные присутствуют в массиве Composer – запрошенный пакет существует, но они отклоняются вашим ограничением настройка базы данных для отслеживания того, какие пользователи нажали на какие ссылки? Недопустимый счетчик ссылок API Google Plus Поля формы POSTing с одинаковым атрибутом имени Рекомендации для статических конструкторов php mysqli WHERE IN (?,?,? …)

PHP / PDO / MySQL: вставка в MEDIUMBLOB хранит плохие данные

У меня есть простое веб-приложение PHP, которое принимает изображения значков через загрузку файлов и сохраняет их в столбце MEDIUMBLOB.

На моей машине (Windows) плюс два Linux-сервера это прекрасно работает. На третьем сервере Linux вставленное изображение повреждено: нечитабельно после SELECT, а длина данных столбца, о котором сообщает функция length () MySQL, примерно на 40% больше, чем размер загруженного файла.

(Каждый сервер подключается к отдельному экземпляру MySQL.)

Конечно, это заставляет меня думать о проблемах с кодировкой и набором символов. В столбцах BLOB нет связанных кодировок, поэтому, скорее всего, наиболее вероятным виновником является PDO и его интерпретация значения параметра для этого столбца.

  • Я пробовал использовать bindValue с PDO :: PARAM_LOB, без эффекта.
  • Я проверил, что изображения принимаются на сервере правильно (т. Е. Читать их после отправки без проблем), поэтому это определенно проблема с DB / PDO.
  • Я искал очевидные различия в конфигурации между серверами, но я не являюсь экспертом в настройке PHP, поэтому я, возможно, что-то пропустил.

Код вставки в основном выглядит следующим образом:

$imagedata = file_get_contents($_FILES["icon"]["tmp_name"]); $stmt = $pdo->prepare('insert into foo (theimage) values (:theimage)'); $stmt->bindValue(':theimage', $imagedata, PDO::PARAM_LOB); $stmt->execute(); 

Любая помощь будет действительно оценена.

ОБНОВЛЕНИЕ : кодировка MySQL по умолчанию на проблемном сервере – utf8; это latin1 на других.

Проблема «решена» путем добавления PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES latin1 COLLATE latin1_general_ci" в конструктор PDO.

Это похоже на плохой дизайн для меня: почему кодировка соединения влияет на данные для двоичного столбца, особенно когда она была идентифицирована как двоичная для самого PDO с PARAM_LOB?

Обратите внимание, что таблицы БД во всех случаях определяются как latin1: это противоречивые кодировки серверов по умолчанию.

Это кажется ошибкой для меня: почему кодировка соединения влияет на данные для двоичного столбца, особенно когда она была идентифицирована как двоичная для самого PDO с PARAM_LOB?

Я не думаю, что это должно быть ошибкой. Я могу себе представить, что всякий раз, когда клиент разговаривает с сервером и говорит, что следующая команда находится в UTF-8, а серверу требуется его в латинском-1, тогда запрос может быть повторно закодирован перед разбором и исполнением. Таким образом, это проблема кодирования для транспортировки данных. Так как весь запрос до синтаксического анализа будет зависеть от этого повторного кодирования, бинарные данные для столбца BLOB также будут изменены.

Из руководства Mysql:

Какой набор символов должен сервер перевести инструкцию после получения?

Для этого сервер использует системные переменные character_set_connection и collation_connection. Он преобразует утверждения, отправленные клиентом от character_set_client к character_set_connection (за исключением строковых литералов, у которых есть интродуктор, такой как _latin1 или _utf8). collation_connection важна для сравнения литеральных строк. Для сравнения строк со значениями столбцов объединение collation_connection не имеет значения, поскольку столбцы имеют собственную сортировку, которая имеет более высокий приоритет сортировки.

Или на обратном пути: данные Latin1 из магазина будут преобразованы в UTF-8, потому что клиент сказал серверу, что он предпочитает UTF-8 для транспортировки.

Идентификатор самого PDO, который вы называете, выглядит как нечто совершенно другое:

PDO :: PARAM_LOB сообщает PDO для сопоставления данных как потока, так что вы можете манипулировать им с помощью PHP Streams API. ( Ref )

Я не эксперт по MySQL, но я бы объяснил это так. Клиенту и серверу необходимо обсудить, какие кодировки они используют, и я предполагаю, что они делают это по какой-то причине.