zoukankan      html  css  js  c++  java
  • 【荐】PHP操作MongoDB GridFS 存储文件,如图片文件

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

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

    特别备注:

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

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

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

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

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

    gfs.php文件

    <?php
    // 连接Mongo并初始化GFS
    $conn = new Mongo(C('127.0.0.1:27017')); //如果设置了密码自己配置DSN
    $db=$conn->selectDB('edu_sns');  // 选择数据库
    $collection = $db->getGridFS('zk_attach'); // 选择集合,相等于选择数据表
    
    // 上传图片
    if (isset($_FILES['upfile'])) {
    
    	// 保存新上传的文件
    	$size = $_FILES['upfile']['size'];
    	$md5 = md5_file($_FILES['upfile']['tmp_name']);
    	$exists = $collection->findOne(array('md5' => $md5,'length' => $size), array('md5'));
    	if (empty($exists)) {
    		$collection->storeUpload('upfile');
    		
    		// 或修改为如下代码,并存入一些自定义参数
    		/*
    		$filename=$_FILES['upfile']['name'];
    		$filetype=$_FILES['upfile']['type'];
    		$tmpfilepath=$_FILES['upfile']['tmp_name'];
    		$id=$gridfs->storeFile($tmpfilepath, array('filename' => $filename, 'filetype' => $filetype));
    		*/
    		
    	} else {
    		unlink($_FILES['upfile']['tmp_name']);
    	}
    	echo "<p>图片路径为: <font color=red>http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}?img={$md5}</font></p>";
    
    } elseif ($id = $_GET['img']) { // 生成图片
    
    	// 索引图片文件
    	$image = $collection->findOne(array('md5' => $id));
    
    	// 设定文档类型,显示图片
    	$img_bytes = $image->getBytes();
    	include_once 'thumb.php';
    	$w = is_numeric($_GET['w']) ? intval($_GET['w']) : 100;
    	Thumb::maxWidth($img_bytes, $w);
    
    } elseif ($id = $_GET['del']) { // 删除图片
    	$s = $collection->remove(array('md5' => $id));
    	header('Location:' . $_SERVER['HTTP_REFERER']);
    
    } else { // 图片列表
    	$cursor = $collection->find();
    	foreach ($cursor as $obj) :
    		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>';
    	endforeach
    	;
    }
    ?>

    thumb.php 缩略图文件

    <?php
    class Thumb {
    
    	/**
    	 * 以最大宽度缩放图像
    	 *
    	 * @param string $im 图像元数据
    	 * @param float $w 最大宽度
    	 */
    	static function maxWidth($im, $w) {
    		if (empty($im) || empty($w) || !is_numeric($w)) {
    			throw new Exception("缺少必须的参数");
    		}
    		$im = imagecreatefromstring($im); // 创建图像
    		list ($im_w, $im_h) = self::getsize($im); // 获取图像宽高
    		if ($im_w > $w) {
    			$new_w = $w;
    			$new_h = $w / $im_w * $im_h;
    		} else {
    			$new_w = $im_w;
    			$new_h = $im_h;
    		}
    		$dst_im = imagecreatetruecolor($new_w, $new_h);
    		imagecopyresampled($dst_im, $im, 0, 0, 0, 0, $new_w, $new_h, $im_w, $im_h);
    		header('Content-type:image/jpeg');
    		imagepng($dst_im);
    		imagedestroy($dst_im);
    		imagedestroy($im);
    	}
    
    	/**
    	 * 以最大高度缩放图像
    	 *
    	 * @param string $im 图像元数据
    	 * @param float $w 最大高度
    	 */
    	static function maxHeight($im, $h) {
    		if (empty($im) || empty($h) || !is_numeric($h)) {
    			throw new Exception("缺少必须的参数");
    		}
    		$im = imagecreatefromstring($im); // 创建图像
    		list ($im_w, $im_h) = self::getsize($im); // 获取图像宽高
    		if ($im_h > $h) {
    			$new_w = $h / $im_h * $im_w;
    			$new_h = $h;
    		} else {
    			$new_w = $im_w;
    			$new_h = $im_h;
    		}
    		$dst_im = imagecreatetruecolor($new_w, $new_h);
    		imagecopyresampled($dst_im, $im, 0, 0, 0, 0, $new_w, $new_h, $im_w, $im_h);
    		header('Content-type:image/jpeg');
    		imagepng($dst_im);
    		imagedestroy($dst_im);
    		imagedestroy($im);
    	}
    
    	/**
    	 * 生成固定大小的图像并按比例缩放
    	 *
    	 * @param string $im 图像元数据
    	 * @param float $w 最大宽度
    	 * @param float $h 最大高度
    	 */
    	static function fixed($im, $w, $h) {
    		if (empty($im) || empty($w) || empty($h) || !is_numeric($w) || !is_numeric($h)) {
    			throw new Exception("缺少必须的参数");
    		}
    		$im = imagecreatefromstring($im); // 创建图像
    		list ($im_w, $im_h) = self::getsize($im); // 获取图像宽高
    		if ($im_w > $im_h || $w < $h) {
    			$new_h = intval(($w / $im_w) * $im_h);
    			$new_w = $w;
    		} else {
    			$new_h = $h;
    			$new_w = intval(($h / $im_h) * $im_w);
    		}
    		//echo "$im_w x $im_h <br/> $new_w x $new_h <br/> $x $y";exit;
    		// 开始创建缩放后的图像
    		$dst_im = imagecreatetruecolor($new_w, $new_h);
    		imagecopyresampled($dst_im, $im, 0, 0, 0, 0, $new_w, $new_h, $im_w, $im_h);
    		header('Content-type:image/jpeg');
    		imagepng($dst_im);
    		imagedestroy($dst_im);
    		imagedestroy($im);
    	}
    
    	/*
    	 * 获取图像大小
    	 * 
    	 * @param string $im 图像元数据
    	 * @return array
    	 */
    	protected static function getsize($im) {
    		return array(
    				imagesx($im),
    				imagesy($im)
    		);
    	}
    }
    ?>

    index.html HTML表单文件

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

    延伸阅读:

    Windows下安装MongoDB

  • 相关阅读:
    Delphi 消息窗口 Application.messagebox
    delphi绑定ComboBox数据
    delphi ComboBox AddObject 组合框下拉取值正确使用方法
    属性分类及其实现
    Delphi 在dbgrideh中表格输入数据时有效性的检查(转)
    XE下显示托盘图标(TrayIcon)
    delphi trayIcon控件,如何实现窗口最小化的时候到系统托盘?
    一步步开发自己的博客 番外篇(7、异步记录日志 和 文章阅读量统计)
    一步步开发自己的博客 .NET版 剧终篇(6、响应式布局 和 自定义样式)
    一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)
  • 原文地址:https://www.cnblogs.com/52php/p/5669950.html
Copyright © 2011-2022 走看看