Pg lo read: примеры (PHP)
pg_lo_read(PgSql\Lob $lob, int $length = 8192): string|falseОсновы функции pg_lo_read
Функция pg_lo_read предназначена для чтения содержимого большого объекта (Large Object) из базы данных PostgreSQL. Она является частью модуля работы с большими объектами (LO), которые позволяют хранить данные размером до 4 ТБ, например, изображения, документы или мультимедийные файлы.
Синтаксис функции: pg_lo_read(resource $large_object, int $length = 8192): string|false
Аргументы функции:
- $large_object — ресурс большого объекта, полученный с помощью функций pg_lo_open или pg_lo_create.
- $length (необязательный) — максимальное количество байтов для чтения. По умолчанию равно 8192. Если передать 0, функция будет считывать данные до достижения конца файла.
Возвращаемые значения: строка с прочитанными данными или false в случае ошибки.
Простые примеры использования
Пример чтения большого объекта с размером блока по умолчанию:
$conn = pg_connect('dbname=mydb');
$oid = 12345; // Идентификатор большого объекта
$handle = pg_lo_open($conn, $oid, 'r');
if ($handle) {
$data = pg_lo_read($handle);
echo 'Прочитано ' . strlen($data) . ' байт';
pg_lo_close($handle);
} else {
echo 'Ошибка открытия объекта';
}Прочитано 8192 байт
Пример с явным указанием размера читаемого блока:
$handle = pg_lo_open($conn, $oid, 'r');
$data = pg_lo_read($handle, 4096); // Чтение 4 КБ
pg_lo_close($handle);Чтение содержимого большого объекта целиком:
$handle = pg_lo_open($conn, $oid, 'r');
$content = '';
while ($chunk = pg_lo_read($handle, 32768)) {
$content .= $chunk;
}
pg_lo_close($handle);
echo 'Общий размер: ' . strlen($content) . ' байт';Общий размер: 24576 байт
Альтернативные функции в PHP
- pg_lo_get — читает весь большой объект и возвращает его содержимое в виде строки. Удобна для объектов небольшого размера.
- pg_lo_export — экспортирует большой объект в файл на сервере. Позволяет сохранить объект непосредственно в файловую систему.
- pg_lo_read_all — отправляет содержимое большого объекта непосредственно в браузер или другой вывод. Полезна для потоковой передачи данных.
pg_lo_read используется для поточного чтения больших объектов с контролем размера блока. pg_lo_get подходит для объектов, которые полностью помещаются в память. pg_lo_export применяется при необходимости сохранения объекта в файл.
Аналоги в других языках и СУБД
В Python для чтения больших объектов используется метод read объекта LargeObject:
import psycopg2
conn = psycopg2.connect('dbname=mydb')
conn.autocommit = True
lo = conn.lobject(12345, 'rb')
data = lo.read(8192) # Чтение 8 КБ
lo.close()В Node.js с использованием библиотеки pg:
const { Client } = require('pg');
const client = new Client();
await client.connect();
const stream = client.query(new Client.QueryStream('SELECT loread(12345, 8192)'));
stream.on('data', chunk => {
console.log(chunk);
});В MySQL аналогом является тип данных BLOB и функции работы с ним:
SELECT SUBSTRING(blob_column, 1, 8192) FROM table WHERE id = 1;В Python и JavaScript часто используются потоковые интерфейсы, тогда как в PHP требуется ручное управление чтением по блокам. MySQL использует совершенно другую модель хранения бинарных данных.
Типичные ошибки и их решение
Ошибка возникает при передаче неверного ресурса в функцию:
$data = pg_lo_read(false, 8192);
var_dump($data);bool(false)
Решение: проверять результат pg_lo_open перед чтением.
Попытка чтения из закрытого большого объекта:
$handle = pg_lo_open($conn, $oid, 'r');
pg_lo_close($handle);
$data = pg_lo_read($handle, 1024);
if ($data === false) {
echo 'Ресурс объекта недействителен';
}Ресурс объекта недействителен
Чтение очень большого объекта целиком может привести к исчерпанию памяти:
$handle = pg_lo_open($conn, $large_oid, 'r');
$content = '';
while ($chunk = pg_lo_read($handle, 0)) { // Чтение всего объекта
$content .= $chunk; // Потенциальная проблема с памятью
}Решение: использовать ограниченный размер блока или экспорт в файл.
Изменения в последних версиях PHP
В PHP 8.0 были улучшены сообщения об ошибках для функций работы с большими объектами. Сама функция pg_lo_read не претерпела значительных изменений в поведении, но теперь более строго типизирована.
Модуль больших объектов PostgreSQL в PHP остается стабильным. В будущих версиях планируется улучшение интеграции с современными методами работы с бинарными данными, но обратная совместимость сохраняется.
Расширенные примеры использования
Пример передачи большого объекта непосредственно в ответ HTTP:
$handle = pg_lo_open($conn, $oid, 'r');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="file.bin"');
while ($chunk = pg_lo_read($handle, 65536)) {
echo $chunk;
flush();
}
pg_lo_close($handle);Чтение и обработка текстового файла, хранящегося как большой объект, по строкам:
$handle = pg_lo_open($conn, $text_oid, 'r');
$buffer = '';
while ($chunk = pg_lo_read($handle, 1024)) {
$buffer .= $chunk;
$lines = explode("\n", $buffer);
$buffer = array_pop($lines);
foreach ($lines as $line) {
echo 'Строка: ' . htmlspecialchars($line) . '<br>';
}
}
if ($buffer !== '') {
echo 'Последняя строка: ' . htmlspecialchars($buffer);
}
pg_lo_close($handle);Пример пошагового сравнения содержимого двух больших объектов:
$handle1 = pg_lo_open($conn, $oid1, 'r');
$handle2 = pg_lo_open($conn, $oid2, 'r');
$are_equal = true;
$block_size = 4096;
do {
$data1 = pg_lo_read($handle1, $block_size);
$data2 = pg_lo_read($handle2, $block_size);
if ($data1 !== $data2) {
$are_equal = false;
break;
}
} while ($data1 !== false && $data2 !== false);
pg_lo_close($handle1);
pg_lo_close($handle2);
echo $are_equal ? 'Объекты идентичны' : 'Объекты различаются';Пример чтения и одновременного расшифрования данных:
$handle = pg_lo_open($conn, $encrypted_oid, 'r');
$key = 'my-secret-key';
$method = 'AES-256-CBC';
$content = '';
while ($chunk = pg_lo_read($handle, 8192)) {
$content .= $chunk;
}
pg_lo_close($handle);
$decrypted = openssl_decrypt($content, $method, $key);
file_put_contents('decrypted.txt', $decrypted);