内置功能,它提供一组文件操作的API以利用MongoDB存储文件,GridFS的基本原理是将文件保存在两个Collection中,一个保存文件索引,一个保存文件内容,文件内容按一定大小分成若干块,每一块存在一个Document中,这种方法不仅提供了文件存储,还提供了对文件相关的一些附加属性(比如MD5值,文件名等等)的存储。

01
<?php
02
// 初始化gridfs
03
$conn = new Mongo(); // 连接MongoDB
04
$db = $conn->photos; // 选择数据库
05
$collection = $db->getGridFS(); // 取得gridfs对象
06
 
07
// gridfs有三种方式存储文件
08
// 第一种直接存储文件
09
$id = $collection->storeFile("./logo.png");
10
 
11
// 第二种存储文件二进制流
12
$data = get_file_contents("./logo.png");
13
$id = $collection->storeBytes($data,array("param" => '附加参数将随图片一起存入'));
14
 
15
// 第三种保存直接表单提交的文件$_FILES
16
$id = $collection->storeUpload('upfile');
17
// 相当于
18
$id = $collection->storeFile($_FILES['upfile']['tmp_name']);
19
 
20
//--------------以上是保存图片--下面开始读取图片----------------
21
 
22
// 保存成功后返回$id = md5字符串
23
$logo = $collection->findOne(array('_id'=>$id)); // 以_id为索引取得文件
24
header('Content-type: image/png'); // 输出图片头
25
echo $logo ->getBytes(); // 输出数据流
26
?>

特别备注:

$id = $collection->storeFile($_FILES['upfile']['tmp_name']); 产生的ID,是MongoDB的 ID对象,而不是一个 字符串!如以下格式:


1
{
2
   "_id": ObjectId("525418525ba8a18c1b000001"),
3
   "filename": "D:\\php\\xampp\\tmp\\php8116.tmp",
4
   "uploadDate": ISODate("2013-10-08T14:36:02.0Z"),
5
   "length": NumberInt(55862),
6
   "chunkSize": NumberInt(262144),
7
   "md5": "a6f19f3434f0b36bb2611cd4c6d82b35"
8
}

$id = strval($id),把上述 ID对象 字符串化,如可得到上述的 525418525ba8a18c1b000001 值,再把这个值存到MySQL数据库中,到时候可通过这个 字符串ID 作为条件,找到相应的MongoDB资源。参考代码如下:

1
$conn = new Mongo(C('127.0.0.1:27017')); //如果设置了密码自己配置DSN
2
$db=$conn->selectDB('edu_sns');  // 选择数据库
3
$collection = $db->getGridFS('zk_attach'); // 选择集合,相等于选择数据表
4
 
5
$id=$_GET['id'];
6
$object=$collection->findOne(array('_id'=>new MongoId($id)));
7
header('Content-type: image/png');
8
echo $object->getBytes();
 

 

 

最近因工作需要研究了下GridFS,并整理了个Demo出来。。分享一下经验。。

gfs.php文件


01
<?php
02
// 连接Mongo并初始化GFS
03
$conn = new Mongo(C('127.0.0.1:27017')); //如果设置了密码自己配置DSN
04
$db=$conn->selectDB('edu_sns');  // 选择数据库
05
$collection = $db->getGridFS('zk_attach'); // 选择集合,相等于选择数据表
06
 
07
// 上传图片
08
if (isset($_FILES['upfile'])) {
09
 
10
    // 保存新上传的文件
11
    $size = $_FILES['upfile']['size'];
12
    $md5 = md5_file($_FILES['upfile']['tmp_name']);
13
    $exists = $collection->findOne(array('md5' => $md5,'length' => $size), array('md5'));
14
    if (empty($exists)) {
15
        $collection->storeUpload('upfile');
16
         
17
        // 或修改为如下代码,并存入一些自定义参数
18
        /*
19
        $filename=$_FILES['upfile']['name'];
20
        $filetype=$_FILES['upfile']['type'];
21
        $tmpfilepath=$_FILES['upfile']['tmp_name'];
22
        $id=$gridfs->storeFile($tmpfilepath, array('filename' => $filename, 'filetype' => $filetype));
23
        */
24
         
25
    } else {
26
        unlink($_FILES['upfile']['tmp_name']);
27
    }
28
    echo "<p>图片路径为: <font color=red>http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}?img={$md5}</font></p>";
29
 
30
} elseif ($id = $_GET['img']) { // 生成图片
31
 
32
    // 索引图片文件
33
    $image = $collection->findOne(array('md5' => $id));
34
 
35
    // 设定文档类型,显示图片
36
    $img_bytes = $image->getBytes();
37
    include_once 'thumb.php';
38
    $w = is_numeric($_GET['w']) ? intval($_GET['w']) : 100;
39
    Thumb::maxWidth($img_bytes, $w);
40
 
41
} elseif ($id = $_GET['del']) { // 删除图片
42
    $s = $collection->remove(array('md5' => $id));
43
    header('Location:' . $_SERVER['HTTP_REFERER']);
44
 
45
} else { // 图片列表
46
    $cursor = $collection->find();
47
    foreach ($cursor as $obj) :
48
        echo '<p><a href="?img=' . $obj->file['md5'] . '&w=800"><img src="?img=' . $obj->file['md5'] . '" border="0" /></a><a href="?del=' . $obj->file['md5'] . '">删除</a></p>';
49
    endforeach
50
    ;
51
}
52
?>

 

thumb.php 缩略图文件

001
<?php
002
class Thumb {
003
 
004
    /**
005
     * 以最大宽度缩放图像
006
     *
007
     * @param string $im 图像元数据
008
     * @param float $w 最大宽度
009
     */
010
    static function maxWidth($im, $w) {
011
        if (empty($im) || empty($w) || !is_numeric($w)) {
012
            throw new Exception("缺少必须的参数");
013
        }
014
        $im = imagecreatefromstring($im); // 创建图像
015
        list ($im_w, $im_h) = self::getsize($im); // 获取图像宽高
016
        if ($im_w > $w) {
017
            $new_w = $w;
018
            $new_h = $w / $im_w * $im_h;
019
        } else {
020
            $new_w = $im_w;
021
            $new_h = $im_h;
022
        }
023
        $dst_im = imagecreatetruecolor($new_w, $new_h);
024
        imagecopyresampled($dst_im, $im, 0, 0, 0, 0, $new_w, $new_h, $im_w, $im_h);
025
        header('Content-type:image/jpeg');
026
        imagepng($dst_im);
027
        imagedestroy($dst_im);
028
        imagedestroy($im);
029
    }
030
 
031
    /**
032
     * 以最大高度缩放图像
033
     *
034
     * @param string $im 图像元数据
035
     * @param float $w 最大高度
036
     */
037
    static function maxHeight($im, $h) {
038
        if (empty($im) || empty($h) || !is_numeric($h)) {
039
            throw new Exception("缺少必须的参数");
040
        }
041
        $im = imagecreatefromstring($im); // 创建图像
042
        list ($im_w, $im_h) = self::getsize($im); // 获取图像宽高
043
        if ($im_h > $h) {
044
            $new_w = $h / $im_h * $im_w;
045
            $new_h = $h;
046
        } else {
047
            $new_w = $im_w;
048
            $new_h = $im_h;
049
        }
050
        $dst_im = imagecreatetruecolor($new_w, $new_h);
051
        imagecopyresampled($dst_im, $im, 0, 0, 0, 0, $new_w, $new_h, $im_w, $im_h);
052
        header('Content-type:image/jpeg');
053
        imagepng($dst_im);
054
        imagedestroy($dst_im);
055
        imagedestroy($im);
056
    }
057
 
058
    /**
059
     * 生成固定大小的图像并按比例缩放
060
     *
061
     * @param string $im 图像元数据
062
     * @param float $w 最大宽度
063
     * @param float $h 最大高度
064
     */
065
    static function fixed($im, $w, $h) {
066
        if (empty($im) || empty($w) || empty($h) || !is_numeric($w) || !is_numeric($h)) {
067
            throw new Exception("缺少必须的参数");
068
        }
069
        $im = imagecreatefromstring($im); // 创建图像
070
        list ($im_w, $im_h) = self::getsize($im); // 获取图像宽高
071
        if ($im_w > $im_h || $w < $h) {
072
            $new_h = intval(($w / $im_w) * $im_h);
073
            $new_w = $w;
074
        } else {
075
            $new_h = $h;
076
            $new_w = intval(($h / $im_h) * $im_w);
077
        }
078
        //echo "$im_w x $im_h <br/> $new_w x $new_h <br/> $x $y";exit;
079
        // 开始创建缩放后的图像
080
        $dst_im = imagecreatetruecolor($new_w, $new_h);
081
        imagecopyresampled($dst_im, $im, 0, 0, 0, 0, $new_w, $new_h, $im_w, $im_h);
082
        header('Content-type:image/jpeg');
083
        imagepng($dst_im);
084
        imagedestroy($dst_im);
085
        imagedestroy($im);
086
    }
087
 
088
    /*
089
     * 获取图像大小
090
     *
091
     * @param string $im 图像元数据
092
     * @return array
093
     */
094
    protected static function getsize($im) {
095
        return array(
096
                imagesx($im),
097
                imagesy($im)
098
        );
099
    }
100
}
101
?>

 

index.html HTML表单文件

01
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
02
<html xmlns="http://www.w3.org/1999/xhtml">
03
<head>
04
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
05
<title>Mongo Gridfs</title>
06
</head>
07
 
08
<body>
09
<form action="gfs.php" method="post" enctype="multipart/form-data">
10
    <input type="file" name="upfile"  />
11
    <input type="submit" value="upload" /> <a href="gfs.php">查看图片</a>
12
</form>
13
</body>
14
</html>