1

最近我们在 mongodb 中集成了 Gridfs 用于存储图像。根据我的要求,以前我们使用 NFS 来获取或存储目录中的图像。图像的速度越来越慢。所以我们集成了 GridFS。

GridFS,但现在我要澄清的是,我们如何在单个请求中获得不止一次的图像并将其显示在浏览器中?因为我们在 mongodb gridfs 分片中填充了近 1L 张照片。但我无法在单个请求中获取多个图像。

下面给出的示例代码。- 以下代码将只返回一张照片。我无法按单个请求获取所有图像。如果有人遇到此类问题,请与我们分享。

方法一:只返回一张图片。

$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);
        }
}

方法 2:它返回所有图像,但与 NFS 一样,每个图像都会获取每个 HTTP 请求。没有储蓄。

$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()."'>";

获取照片.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);
4

1 回答 1

2

我看不出如何在单个请求中返回多个文件,除非您使用 PHP 的压缩和存档扩展之一将它们组合成一个文件,然后将其作为 HTTP 响应中继。

如果图像很小,另一种方法是将它们作为base64 编码的 Data URIs嵌入到 HTML 中。该技术通常用于在 CSSbackground-image值中嵌入小图像(图标大小);但是,它不适合大图像,因为存储开销非常高。


关于您的第一个代码示例中的此查询:

$gridFS->find(array("metadata.memberid"=>"CMD34123"))

我意识到这一行已被注释掉,但如果您正在运行这样的查询,我建议您编制索引metadata.memberid以避免扫描fs.files集合中的每个文档。

您正在进行的迭代尝试连续打印多个JPG 图像的内容类型标题和字节内容。PHP 的header()函数不能以这种方式多次调用。

您可能能够利用多部分 HTTP 响应来发回多个图像,但浏览器支持可能会出现问题(请参阅:this question from a few years back)。


在您的getphoto.php源代码中,您打算使用字符串参数调用MongoGridFS::findOne() 。您应该知道,用户可以利用查询字符串,因此它$_REQUEST['filename']实际上是一个数组(请参阅:关于该主题的这篇文章)。在将请求参数传递给findOne().

此外:

  • 这将在该filename字段上进行查询,因此您应该确保它已被索引。
  • 根据fs.files 规范,该filename字段是可选的,不一定是唯一的。GridFS 中的多个文件很可能具有相同的文件名。

考虑到以上几点,使用 ObjectId 的 24 个十六进制字符作为请求参数,构造一个MongoId并在_id字段上使用它进行查询(或使用MongoGridFS::get())可能更容易。在这种情况下,我之前关于验证请求参数的观点仍然适用——它允许您使用默认_id索引。

于 2013-06-27T21:46:53.800 回答