У меня есть база данных Firebird с полем blob для изображений в формате base64. Если я пытаюсь загрузить закодированное изображение размером более 32 КБ, это дает мне исключение:
org.firebirdsql.jdbc.FBSQLException: исключение GDS. 335544569. Динамическая ошибка SQL Код ошибки SQL = -104 Сообщение для кода 336397331 не найдено.
Это означает, что строковый литерал с X байтов превышает максимальную длину Y байтов. Действительно ли большой двоичный объект Firebird такой маленький, и мне нужно, например, изменить свою БД для mySQL? У меня нет ни времени, ни знаний php, чтобы создавать back-end api для картинок.
Кроме того, зачем раздувать изображения до больших данных base64? Просто сохраните их как есть, в двоичном виде.
Не вставляйте строковые литералы в BLOB. Используйте параметризованные запросы и помещайте данные в BLOB через них. В этом случае они могут оставить не менее 2 гигабайт.
Как добавить изображение блоба FIrebird в php?
pdo напрямую вставлять изображение в базу данных - всегда вставляя BLOB - 0B
Большие двоичные объекты в Firebird могут быть намного больше 32 килобайт. В зависимости от размера страницы базы данных максимальный размер одного большого двоичного объекта может достигать чуть менее 4 ГБ (размер страницы 4096) или более 128 ГБ (размер страницы 16384).
Проблема в том, что, судя по всему, вы создали запросы, объединяя значения в строку запроса вместо использования параметров. Объединение значений в строку запроса небезопасно (оно делает вас уязвимым для SQL-инъекций), но в этом случае вы также достигаете жесткого ограничения. В Firebird строковые литералы ограничены 32 килобайтами (или — начиная с Firebird 3 — 64 килобайтами (фактически 64 килобайта — 3) при назначении большому двоичному объекту).
Если вы хотите присвоить большие значения, вы должны использовать подготовленный оператор с параметрами. Например (ПРИМЕЧАНИЕ: я публикую код Java, потому что ошибка, которую вы разместили в своем вопросе, создается Jaybird, драйвером JDBC Firebird (для Java)):
try (var pstmt = connection.prepareStatement("insert into images (filename, blobdata) values (?, ?)")) {
pstmt.setString(1, "filename.jpg");
pstmt.setBinaryStream(2, someInputStreamForTheData);
// or: pstmt.setBytes(2, fileBytes);
pstmt.executeUpdate();
}
Кроме того, сохранение изображений в кодировке base64 в большом двоичном объекте (при условии, что BLOB SUB_TYPE BINARY
, а не BLOB SUB_TYPE TEXT
) не имеет для меня особого смысла, изображения представляют собой двоичные данные, а большие двоичные объекты предназначены для сохранения двоичных данных. Использование base64 вводит ненужные накладные расходы на хранение (1 дополнительный байт на каждые 3 байта данных).
Да, я пытался реализовать это в своем приложении для Android, но похоже, что «setBinartStream» еще не реализован, поскольку у Android нет официально поддерживаемой версии, а драйвер достаточно старый. Но это не предмет данного вопроса.
@ezh Вы не должны подключаться напрямую к базе данных Firebird с Android (или любой удаленной базы данных в этом отношении), более целесообразным подходом является создание REST API на Java или другом языке и заставить ваше приложение Android общаться с этим REST API.
Да, я сейчас разрабатываю API для этого :)
BLOB-объекты могут быть любой длины, но BLOB-объекты НЕ являются строковыми литералами. Похоже, вы используете сращивание строк, которое является хрупким (вы не можете быть уверены в представлении типов данных, таких как даты/время/поплавки) и опасными (инъекции). Это ненормально. Используйте параметры. bobby-tables.com/php