Reputation: 897
Recently we integrated the Gridfs in mongodb for storing images. For my requirement, previously we have used NFS for getting or storing an images in directory. its getting more slow down for an images. So we integrated GridFS.
GridFS, but now my clarification is how we can get the more than once images on single request and show it in the browser?. Because we populated near to 1L photos in mongodb gridfs sharding. But i cant fetch the more than one images on single request.
Sample Code given below. - Following code will return only one photos. I cant fetch the all images on single request. If anyone face this kind of issues, pls share us.
Method 1: It returns only one image.
$mongo = new Mongo("192.168.0.8:27017");
$db = $mongo->myfiles;
$gridFS = $db->getGridFS();
$cursor = $gridFS->find()->limit(10); - it will return one than one images
/*$cursor = $gridFS->find(array("metadata.memberid"=>"CMD34123")); - it will return one than one images, because the member having more than one images.*/
foreach ($cursor as $obj)
{
header("Content-Type: image/jpg");
$stream = $obj->getResource();
while (!feof($stream)) {
echo fread($stream, 51200);
}
}
Method 2: It returns all images, but same like NFS each image will fetch each HTTP request. No saving.
$mongo = new Mongo("192.168.0.8:27017");
$db = $mongo->myfiles;
$gridFS = $db->getGridFS();
$cursor = $gridFS->find()->limit(10);
foreach ($cursor as $obj)
echo "<img src='getphoto.php?filename=".$obj->getFilename()."'>";
getphoto.php:
$mongo = new Mongo("192.168.0.8:27017");
$db = $mongo->myfiles;
$gridFS = $db->getGridFS();
/*$image = $gridFS->findOne($_REQUEST['filename']);*/
header("Content-Type: image/jpg");
echo $stream = $image->getResource();
while (!feof($stream))
echo fread($stream, 51200);
Upvotes: 1
Views: 1798
Reputation: 6922
I don't see how you would return multiple files in a single request unless you were using one of PHP's compression and archive extensions to combine them into a single file, which in turn was relayed as the HTTP response.
If the images are small, an alternative would be embedding them in HTML as base64-encoded Data URIs. That technique is often used for embedding small images (icon size) in CSS background-image
values; however, it's not suitable for large images, since the storage overhead is quite high.
Regarding this query in your first code example:
$gridFS->find(array("metadata.memberid"=>"CMD34123"))
I realize this line was commented out, but if you are running such a query, I would suggest indexing metadata.memberid
to avoid scanning each document in the fs.files
collection.
The iteration you were doing attempts to print a content-type header and byte contents of several JPG images in succession. PHP's header() function cannot be called multiple times in this manner.
You may be able utilize multi-part HTTP responses to send back multiple images, but browser support could be problematic (see: this question from a few years back).
In your getphoto.php
source, you're intending to call MongoGridFS::findOne() with a string parameter. You should be aware that users could exploit the query string so that $_REQUEST['filename']
is actually an array (see: this post on the subject). You would do well to check the request parameter and/or cast it to a string before passing it to findOne()
.
Additionally:
filename
field, so you should make sure that it's indexed.fs.files
specification, the filename
field is optional and not necessarily unique. It's quite possible that multiple files in GridFS could have the same filename.Considering the above points, it may be easier to just use the 24 hexadecimal characters of the ObjectId as a request parameter, construct a MongoId, and query with that on on the _id
field (or use MongoGridFS::get()). My previous points on validating the request parameter would still stand in this case -- it would allow you to use the default _id
index.
Upvotes: 2