• [智能架构系列]Buddy框架图片文件云存储模块实现



    [智能架构系列]Buddy框架图片文件云存储模块实现


    引子
    最近很久没有写文章了,主要是忙于公司的项目,也给自己一个深度挖掘的方向,另外生活也出现了很大的变动,现在终于憋不住了。订阅技术博文是技术者必须做的一件事情,每天打开google reader总是会有所发现有所惊喜继而是感慨。本次主要来介绍下图片的云存储方面的技术实现,不管是对于云技术实践,还是降低相关的运维成本,都是很有效果的,不信就往下看吧!

    关键字:图片云存储 又拍云存储 PHP图片存储 廉价高速图片存储

    正文
    上周看了磊哥的文章 又拍云实战 http://www.blogkid.net/archives/2782.html 后很有收获就觉得去试试又拍云存储的服务http://www.upyun.com/,就去注册然后申请试用了。
    本次upyun.com的认证方式很让我意外,竟然是客服打电话过来确认,这点服务感觉还是挺好的,从这里感觉还是蛮重视用户的。特别要说的是,今天是星期天我又在这里宣传upyun.com的服务,就和同事说了下,结果他去注册了,竟然在半小时后就接到了客服人员的电话了,感觉这个确认还是很及时的,体验很好,这点感觉还是很不错的。
    试用就开始吧,为什么要试用又拍云存储服务呢?这点磊哥的文章中就已经说的很清楚了,这里我做归纳补充下:
    1,图片服务器的托管及运维费用挺高的,而且峰值带宽觉得了大部分成本,且运维的软硬成本增大
    2,单机达不到CDN功效,需要CDN支持的话,花费就更大了
    3,图片的处理及图片的缓存,需要配置nginx的静态缓存图片,需要做系统设计扩展图片类的保存图片及缩略图功能
    4,图片的备份,对于图片的备份是个问题需要用rsync同步到备份机器,添加了运维成本和开发成本

    基于以上原因,自己开发及部署图片服务的代价还是很大的,所以这个也是极力推荐使用又拍云存储www.upyun.com的原因了,至于大家说的upyun.com是否稳定,磊哥提到的猛买网用了2个月还是没问题的,我也相信@gofeeling和又拍的技术实力的。
    如何申请及开通就请详细参看磊哥的博文吧,本篇主要更细致化的讲解技术实现。


    首先,设计表结构
    id,filename,desc,createtime,status,remoteurl,url,model,user_id
    本次主要用到的字段有 filename 及 model
    构造图片的访问地址 $staticUrl / $model / $filename
    例如: http://img001.img.woshimaijia.com/user/testuser.jpg
    考虑到图片表可能进行分表,这里的id使用了 17位的bigint 时间递增

    其次,完善图片类
    首先图片的处理流程分为如下
    1.用户从表单中上传的图片
    2.已经上传的图片
    现在这2部分的图片都需要迁移到又拍云存储中,而且都需要做本地进行备份。
    所以处理的逻辑如下
    用户上传 --> 图片保存到WebServer --> 调用ImageUpload类将图片上传到upyun.com --> 更新数据库表
    图片读取 --> 获取图片id集合 --> 调用getImage方法拼接URL --> 返回图片URL

    下午调试了下实现了一些HTTP REST的图片使用类,主要包含了
    上传,下载,删除,查看使用空间
    具体代码如下

    <?php
    // +----------------------------------------------------------------------
    // | Buddy Framework
    // +----------------------------------------------------------------------
    // | Copyright (c) 2011 http://buddy.woshimaijia.com All rights reserved.
    // +----------------------------------------------------------------------
    // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
    // +----------------------------------------------------------------------
    // | Author: xinqiyang <xinqiyang@gmail.com>
    // +----------------------------------------------------------------------
    /**
     * Image Upload service
     * use upaiyun.com image service
     * 使用了又拍云存储的图片服务
     * @author xinqiyang
     *
     */
    class ImageUpload
    {
    	protected $_config = array();
    	public function __construct()
    	{
    		$this->_config = C('imageservice');
    	}
    
    	/**
    	 * update file to upaiyun.com
    	 * 上传图片保存到又拍云存储网
    	 * @param unknown_type $object
    	 * @param unknown_type $filename
    	 * @param unknown_type $path
    	 */
    	public function put($object,$filename,$path)
    	{
    		$postField = file_get_contents((realpath($path)));
    		$process = curl_init($this->_config['api'].'/'.$this->_config['bucketname'].'/'.$object.'/'.$filename);
    		curl_setopt($process, CURLOPT_POST, 1);
    		curl_setopt($process, CURLOPT_POSTFIELDS, $postField);
    		curl_setopt($process, CURLOPT_USERPWD, $this->_config['username'].':'.$this->_config['userpass']);
    		curl_setopt($process, CURLOPT_HTTPHEADER, array('Expect:', "Mkdir:true"));
    		curl_setopt($process, CURLOPT_HEADER, 0);
    		curl_setopt($process, CURLOPT_TIMEOUT, 30);
    		curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
    		curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
    		$result = curl_exec($process);
    		$code = curl_getinfo($process, CURLINFO_HTTP_CODE);
    		curl_close($process);
    		return array('code'=>$code,'info'=>$result);
    	}
    
    	public  function get($object,$filename)
    	{
    		$process = curl_init($this->_config['api'].'/'.$this->_config['bucketname'].'/'.$object.'/'.$filename);
    		curl_setopt($process, CURLOPT_USERPWD, $this->_config['username'].':'.$this->_config['userpass']);
    		curl_setopt($process, CURLOPT_HEADER, 0);
    		curl_setopt($process, CURLOPT_TIMEOUT, 30);
    		curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
    		curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
    		$result = curl_exec($process);
    		$code = curl_getinfo($process, CURLINFO_HTTP_CODE);
    		curl_close($process);
    		return array('code'=>$code,'info'=>$result);
    	}
    
    	public  function delete($object,$filename)
    	{
    		$process = curl_init($this->_config['api'].'/'.$this->_config['bucketname'].'/'.$object.'/'.$filename);
    		curl_setopt($process, CURLOPT_CUSTOMREQUEST, 'DELETE');
    		curl_setopt($process, CURLOPT_USERPWD, $this->_config['username'].':'.$this->_config['userpass']);
    		curl_setopt($process, CURLOPT_HEADER, 0);
    		curl_setopt($process, CURLOPT_TIMEOUT, 30);
    		curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
    		curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
    		$result = curl_exec($process);
    		$code = curl_getinfo($process, CURLINFO_HTTP_CODE);
    		curl_close($process);
    		return array('code'=>$code,'info'=>$result);
    	}
    
    	public  function usage()
    	{
    		 $process = curl_init($this->_config['api'].'/'.$this->_config['bucketname'].'?usage'); 
    		 curl_setopt($process, CURLOPT_USERPWD, $this->_config['username'].':'.$this->_config['userpass']);
    		 curl_setopt($process, CURLOPT_HEADER, 0); 
    		 curl_setopt($process, CURLOPT_TIMEOUT, 30); 
    		 curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); 
    		 $result = curl_exec($process);
    		$code = curl_getinfo($process, CURLINFO_HTTP_CODE);
    		curl_close($process);
    		return array('code'=>$code,'info'=>$result);
    	}
    	
    	/**
    	 * save file or image to upaiyun.com then update db
    	 * 先保存数据到又拍云存储,然后在更新数据库
    	 * @param string $model
    	 * @param string $filename   保存文件名
    	 * @param mixed $streamFile  流文件或者是图片路径
    	 * @param bigint $id ID
    	 * @param bigint $user_id userid
    	 */
    	public  function save($model,$filename='',$streamFile='',$id='',$user_id)
    	{
    		$result = $this->put($model, $filename,$streamFile);
    		$id = empty($id) ? objid() : $id;
    		$filename = empty($filename) ? $id : $filename;
    		if($result['code'] == 200)
    		{
    			$array = array(
    				'id'=>$id,
    				'filename'=>$filename,
    				'model'=>$model,
    				'status'=> 0,
    				'user_id'=>$user_id,
    			);
    			return ImageService::add($array);
    		}
    		return $result;
    	}
    	
    	//从缓存获取image表中的 model filename 然后拼接成url 返回
    	public  function  display($id)
    	{
    		$url = $this->_config['url'];
    		return $this->_config['url'].ImageService::getImage($id);
    	}
    
    
    }

    结语
    其实使用API的方式操作其实会比现在的繁琐一些,保存做WebServer上的文件只是作为一个备份文件的形式存在,等同步到备份地址后删除即可,对于同步到备份服务器后即可进行缩略图的操作,或者是通过upyun的url将用到的图片做download一份到备份服务器即可,另外又拍的存储的价格现在看来还是挺实惠的,感觉非常的不错,推荐大家试用。其他国内更多的靠谱的云产品的出现!

  • 相关阅读:
    MySQL的char和varchar针对空格的处理
    单KEY业务,数据库水平切分架构实践
    接口测试学习笔记1-接口测试的用例设计
    Robot Framework源码解析(2)
    Robot Framework 源码解析(1)
    Python学习笔记1 -- TypeError: 'str' object is not callable
    OKHttp源码学习同步请求和异步请求(二)
    OKHttp源码学习--HttpURLConnection HttpClient OKHttp Get and post Demo用法对比
    Javapoet源码解析
    Universal-Image-Loader源码解解析---display过程 + 获取bitmap过程
  • 原文地址:https://www.cnblogs.com/scotoma/p/2276291.html
Copyright © 2020-2023  润新知