Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image/Media Server That Works With Postgres

I was recently had an nginx + php-fpm server that was serving images like so:

header('Content-Type: image/png');
echo file_get_contents('example_image.png');
exit();

What I am came to realize, whether the image was cached or not, there was a huge peformance hit on the server. CPU utilization was extremely high, 100% with a minimal amount of connections. So I started to offload the images to a CDN and there was an immediate performance improvement but in some cases I still do require the image to be served through a server, which has brought me to the idea of image/media server.

My question is, is there a specific type of server that I should be using? One that can communicate with a database to find the images location and serve it? File system type? Or am I better off keeping just firing up another nginx + php-fpm instance and create a cdn like structure implementation where:

media.example.com 

points only to that server, thus there is no performance impact on the web server?

like image 939
Devin Dixon Avatar asked Jul 25 '26 14:07

Devin Dixon


1 Answers

Your problem is that you're treating your image like a string instead of a stream. There's absolutely no need to load it all up in php using file_get_contents() and proceeding to echo the mess. Look up things such as readfile() and PG-related LOB functionality:

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;

http://php.net/manual/en/function.readfile.php

$db = new PDO('pgsql:dbname=test host=localhost', $user, $pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->beginTransaction();
$stmt = $db->prepare("select oid from BLOBS where ident = ?");
$stmt->execute(array($some_id));
$stmt->bindColumn('oid', $oid, PDO::PARAM_STR);
$stmt->fetch(PDO::FETCH_BOUND);
$stream = $db->pgsqlLOBOpen($oid, 'r');
header("Content-type: application/octet-stream");
fpassthru($stream);

http://php.net/manual/en/pdo.pgsqllobopen.php

Along similar lines, look into cache-control related headers. There's no need to resend an image that is already in the browser's cache. Try to send 304 Not Modified when possible:

Make PHP page return "304 Not Modified" if it hasn't been modified

like image 154
Denis de Bernardy Avatar answered Jul 28 '26 04:07

Denis de Bernardy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!