基于MongoDb的S3实现

【原文】
http://www.fuchaoqun.com/2010/05/s3-on-mongodb-with-php/

原理是利用MongoDb的GridFS,伸展性方面交由MongoDb的auto sharding去实现,这里用PHP给MongoDb绑了个S3出来,支持选择文件存储节点,支持文件分目录存储,这样的好处是对于一些受时间影响比较明显的文件,可以按照年月的形式存储,减轻历史包袱。

首先,配置MongoDb GridFS节点信息:
<?php
$s3Config = array(
    'foo' => array(
        'server' => '127.0.0.1',
        'database' => 'test',
        'user' => 'test',
        'password' => 'foobar',
        'domain' => 'http://s3.foobar.com'
    ),
 
    'bar' => array(
        'server' => '127.0.0.1',
        'database' => 'test',
        'user' => 'test',
        'password' => 'foobar',
        'domain' => 'http://s3.foobar.com'
    ),
);

MongoDb的S3绑定:
<?php
/**
 * 统一文件存储
 *
 */
class Api_S3
{
    protected $_node;
 
    protected $_dir;
 
    protected $_config;
 
    /**
     * 构造函数
     *
     * @param string $node
     * @param string $dir
     * @param array $config
     */
    public function __construct($node, $dir = null, $config = null)
    {
        $this->_config = $config;
 
        $this->path($node, $dir, false);
    }
 
    /**
     * 设置文件路径
     *
     * @param string $node
     * @param string $dir
     * @return Api_S3
     */
    public function path($node, $dir, $connect = true)
    {
        $this->_node = $node;
        $this->_dir = empty($dir) ? 'fs' : $dir;
 
        if (empty($this->_config[$this->_node])) {
            throw new Cola_Exception('Api_S3: invalidate node');
        }
 
        if ($connect) {
            $this->_gridFS = $this->_gridFS();
        }
 
        return $this;
    }
 
    /**
     * GridFS
     *
     * @return MongDbGridFS
     */
    protected function _gridFS()
    {
        $mongo = new Cola_Com_Mongo($this->_config[$this->_node]);
 
        return $mongo->gridFS($this->_dir);
    }
 
    /**
     * 获得文件句柄
     *
     * @param string $name
     * @return MongoGridFSFile
     */
    public function file($name)
    {
        if (empty($this->_gridFS)) {
            $this->_gridFS = $this->_gridFS();
        }
 
        return $this->_gridFS->findOne(array('filename' => $name));
    }
 
    /**
     * 获得文件内容
     *
     * @param string $name
     */
    public function read($name)
    {
        $file = $this->file($name);
 
        return $file->getBytes();
    }
 
    /**
     * 写入文件
     *
     * @param string $name
     * @param string $data
     * @param array $extra
     * @param boolean $overWrite
     * @return boolean
     */
    public function write($name, $data, $extra = array(), $overWrite = false)
    {
        $extra = (array)$extra + array('filename' => basename($name));
 
        if ($filetype = $this->_type($name)) {
            $extra['filetype'] = $filetype;
        }
 
        if ($this->file($extra['filename'])) {
            if ($overWrite) {
                $this->delete($extra['filename']);
            } else {
                throw new Cola_Exception('Api_S3: file exists');
            }
        }
 
        return $this->_gridFS->storeBytes($data, $extra);
    }
 
    /**
     * 复制系统文件
     *
     * @param string $file
     * @param array $extra
     * @param boolean $overWrite
     * @return boolean
     */
    public function copy($file, $extra = array(), $overWrite = false)
    {
        $extra = (array)$extra + array('filename' => basename($file));
 
        if ($filetype = $this->_type($file)) {
            $extra['filetype'] = $filetype;
        }
 
        if ($this->file($extra['filename'])) {
            if ($overWrite) {
                $this->delete($extra['filename']);
            } else {
                throw new Cola_Exception('Api_S3: file exists');
            }
        }
 
        return $this->_gridFS->storeFile($file, $extra);
    }
 
    /**
     * 删除文件
     *
     * @param string $name
     * @return boolean
     */
    public function delete($name)
    {
        if (empty($this->_gridFS)) {
            $this->_gridFS = $this->_gridFS();
        }
 
        return  $this->_gridFS->remove(array('filename' => $name));
    }
 
    /**
     * 获得文件地址
     *
     * @param string $name
     * @param string $default
     * @return string
     */
    public function getUrl($name, $default = false)
    {
        $data = array(
            'domain' => rtrim($this->_config[$this->_node]['domain'], '/'),
            'path'   => $this->_node . (('fs' == $this->_dir) ? '' : $this->_dir),
            'name'   => $name
        );
        return  implode('/', $data);
    }
 
    /**
     * 设置文件属性
     *
     * @param string $name
     * @param array $attr
     * @return boolean
     */
    public function setAttr($name, $attr)
    {
        if (!$file = $this->file($name)) {
            throw new Cola_Exception('Api_S3: file not exists');
        }
 
        $file->file = $attr + $file->file;
 
        return $this->_gridFS->save($file->file);
    }
 
    /**
     * 获得文件属性
     *
     * @param string $name
     * @return array
     */
    public function getAttr($name)
    {
        $file = $this->file($name);
        return $file->file;
    }
 
    /**
     * 获得文件类型
     *
     * @param string $file
     * @return string
     */
    protected function _type($file)
    {
        return mime_content_type($file);
    }
}

文件存入,支持自选节点,自定义目录,自定义文件名,可以自动添加文件类型:
<?php
$s3 = new Api_S3($node, $dir, $s3Config);
$s3->copy($file, array('filename' => $name, 'filetype' => $type));

文件读取,以”http://s3.foobar.com/foo/201005/foobar.jpg”为例,foo映射到节点名,201005映射到目录名,foobar.jpg映射到文件名:
<?php
$s3 = new Api_S3($node, $dir, $s3Config);
$file = $s3->file($name);
 
Cola_Response::lastModified($file->file['uploadDate']->sec);
Cola_Response::etag($file->file['md5']);
 
if (isset($file->file['filetype'])) {
    header("Content-Type: {$file->file['filetype']}");
}
 
echo $file->getBytes();

注意到我们利用了文件的修改时间设置http头的last modified,以及用文件的md5信息设置etag值,这样的好处是可以大大减少带宽使用,当然,你也可以设置expire时间来减少重复请求。

关于性能问题,可以在PHP读取的上一层,加一个Squid之类的反向代理服务,基本上就不会有问题.

时间: 2024-09-29 07:22:06

基于MongoDb的S3实现的相关文章

如何基于MongoDB打造.Net的分布式Session子系统

Taobao有她自己的分布式session框架,.net阵营也不能落后了,在下做了个 基于MongoDB的支持最多26台MongoDB的分布式Session框架. 先看看配置文件: <?xml version="1.0" encoding="utf-8" ?> <MongoDBSession> <DbName>SessionDB</DbName> <IdentityMap Identity="A&quo

基于MongoDB的高并发高可用政府云平台架构实践

3月12日下午在阿里巴巴西溪园区,举行了MongoDB杭州用户交流会.微软MSDN特邀讲师徐雷分享<基于MongoDB的政府云平台高并发高可用HA架构实践 >,从自身实践出发,讲述了政府云平台分层.技术栈选型.物理架构.API架构及DB数据库架构的设计思路和方法.   以下内容根据现场分享和演讲PPT整理而成.   学习MongoDB的重要性 目前,几乎所有国内外的互联网大公司都在用MongoDB,学习企业需要的技术很重要.   MongoDB优点   相比较关系型数据库而言,MongDB有两

基于MongoDB的高校SNS系统设计与实现

基于MongoDB的高校SNS系统设计与实现 胡恒 SNS(Social Networking Services)社会网络服务,又称社交网络服务,是一种透过人际网络形成的互联网应用服务.其中,专门为校园内学生服务的SNS网站被称为校园SNS网站.介绍使用SpringMVC+MongoDB架构高校SNS系统的关键技术.架构设计方案与实现. 基于MongoDB的高校SNS系统设计与实现

基于 MongoDB的云数据管理技术的研究与应用

基于 MongoDB的云数据管理技术的研究与应用 北京交通大学 刘一梦 介绍了云计算环境下NoSQL系统的概念.特征和理论基础,分析主流NoSQL系统的设计原理和特征,并将NoSQL系统与传统的关系型数据库在数据模式.系统架构.读写特性.可扩展性等多个方面进行了详细的分析比较.通过分析对比得出结论:对于云计算环境中的海量数据存储和处理等问题,NoSQL系统是优于传统关系型数据库的解决方案.然后以MongoDB数据库为例,分析其高扩展性集群的架构及原理.深入研究了自动分片集群所使用的均衡算法,针对

基于MongoDB GridFS的图片存储

它是mongodb的一个子模块,使用GridFS可以基于mongodb来持久存储文件.并且支持分布式应用(文件分布存储和读取).GridFS是mongodb中用户存储大对象的工具,对于mongodb,BSON格式的数据(文档)存储有尺寸限制,最大为16M.但是在实际系统开发中,经常会有上传图片或者文件的功能,这些文件可能尺寸会很大..我们可以借用Gridfs来辅助实现这些文件的管理. Mongo GFS的文件表是由 表名.files和 表名.chunks 构成,前者是文件信息构成,后者是文件的内

基于MongoDB构建阿里云MongoDB云数据库服务

6月24日至25日,由中国开源软件推进联盟(COPU)主办的"第十一届开源中国开源世界高峰论坛"在北京成功召开.本届论坛以"深化开源交流,壮大开源平台,服务万众创新,发展共享经济"为主题. 阿里云资深开发数据库工程师郑涔(花名明俨),受邀参与了这次大会,为大家介绍了阿里云与开源项目MongoDB的故事,他的演讲内容大致可分为三部分: MongoDB简介:主要介绍MongoDB项目 利用MongoDB搭建云数据库服务 云数据库MongoDB社区建设 以下是郑涔发言整理

基于MongoDB与NodeJS构建物联网系统

目标 基于阿里云服务快速构建物联网系统 场景介绍和架构设计 端的数据采集与通信协议 利用Node.js构建服务框架 MongoDB数据建模与存储实践 EMR大数据分析 准备工作 ECS MongoDB EMR Alinode 中间件代码 注意事项:ECS,MongoDB 可以选择按量计费的服务. 实例申请 Step0 登录云中沙箱拿到阿里云账号 Step1 利用上面拿到的train***@aliyun-inc.com的阿里云账号,登陆阿里云官网 Step2 控制台新建实例 新建实例: https

基于 MongoDB 及 Spring Boot 的文件服务器的实现

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案.它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型. 本文将介绍通过 MongoDB 存储二进制文件,从而实现一个文件服务器 MongoDB File Server. 文件服务器的需求 本文件服务器致力于小型文件的存储,比如博客中图片.普通文档等.由于MongoDB 支持多种数据格式的存储

MongoDB资料大全

MongoDB是一个开源的.基于分布式的.面向文档存储的非关系型数据库.是非关系型数据库当中功能最丰富.最像关系数据库的.MongoDB由C++编写, MongoDB可以运行在Windows.unix.OSX.Solaris系统上,支持32位和64位应用,提供多种编程语言的驱动程序.旨在为WEB应用提供可扩展的高性能数据存储解决方案.MongoDB高性能.易部署.易使用,存储数据非常方便.MongoDB最大的特点是支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数