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 > |