GridFS是MongoDB的一个内置功能,它提供一组文件操作的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 > |