开发者社区> 问答> 正文

用于ThinkPHP3.2的阿里云OSS轻量级驱动

我能吐槽为啥那php的sdk需要那么大一坨东西么?平常使用也就是个上传而已,就不能弄个简单点的么?
理论上我只需要简单的上传文件而已,不需要那么多东西,于是自己写了一下。
以下代码保存到/yourpath/ThinkPHP/Library/Think/Upload/Driver/Oss.class.php即可
<?php

// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 废墟 <r.anerg@gmail.com> <http://anerg.com>
// +----------------------------------------------------------------------

namespace Think\Upload\Driver;

class Oss {

    const OSS_HOST = 'oss.aliyuncs.com';

    /**
     * 上传文件根目录
     * @var string
     */
    private $rootPath;

    /**
     * 上传错误信息
     * @var string
     */
    private $error  = '';
    private $config = array(
        'access_id'  => '', //阿里云Access Key ID
        'access_key' => '', //阿里云Access Key Secret
        'bucket'     => '', //空间名称
        'timeout'    => 90, //超时时间
    );

    /**
     * 构造函数,用于设置上传根路径
     * @param array  $config FTP配置
     */
    public function __construct($config) {
        /* 默认FTP配置 */
        $this->config = array_merge($this->config, $config);
    }

    /**
     * 检测上传根目录(阿里云上传时支持自动创建目录,直接返回)
     * @param string $rootpath   根目录
     * @return boolean true-检测通过,false-检测失败
     */
    public function checkRootPath($rootpath) {
        /* 设置根目录 */
        $this->rootPath = trim($rootpath, './') . '/';
        return true;
    }

    /**
     * 检测上传目录(阿里云上传时支持自动创建目录,直接返回)
     * @param  string $savepath 上传目录
     * @return boolean          检测结果,true-通过,false-失败
     */
    public function checkSavePath($savepath) {
        return true;
    }

    /**
     * 创建文件夹 (阿里云上传时支持自动创建目录,直接返回)
     * @param  string $savepath 目录名称
     * @return boolean          true-创建成功,false-创建失败
     */
    public function mkdir($savepath) {
        return true;
    }

    /**
     * 保存指定文件
     * @param  array   $file    保存的文件信息
     * @param  boolean $replace 同名文件是否覆盖
     * @return boolean          保存状态,true-成功,false-失败
     */
    public function save($file, $replace = true) {
        $_headers = array('Content-Type: ' . $file['type']);
        $resource = fopen($file['tmp_name'], 'r');

        $path = $this->rootPath . $file['savepath'] . $file['savename'];

        $uri = "/{$this->config['bucket']}{$path}";
        $ch  = curl_init('http://' . self::OSS_HOST . $uri);

        $date = gmdate('D, d M Y H:i:s \G\M\T');

        array_push($_headers, "Date: {$date}");

        $sign_string = "PUT\n\n" . $file['type'] . "\n" . $date . "\n" . $uri;
        $sign        = $this->hex_to_base64(hash_hmac('sha1', $sign_string, $this->config['access_key']));

        array_push($_headers, 'Authorization: OSS ' . $this->config['access_id'] . ':' . $sign);

        fseek($resource, 0, SEEK_END);
        $length = ftell($resource);
        fseek($resource, 0);

        array_push($_headers, "Content-Length: {$length}");

        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_INFILE, $resource);
        curl_setopt($ch, CURLOPT_INFILESIZE, $length);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers);
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->config['timeout']);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
        $response = curl_exec($ch);
        $status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        fclose($resource);
        if ($status == 200) {
            return true;
        } else {
            $this->error = $response;
            return false;
        }
    }

    /**
     * 获取最后一次上传错误信息
     * @return string 错误信息
     */
    public function getError() {
        return $this->error;
    }


    private function hex_to_base64($str) {
        $result = '';

        for ($i = 0; $i < strlen($str); $i += 2) {
            $result .= chr(hexdec(substr($str, $i, 2)));
        }

        return base64_encode($result);
    }

}

使用方法也比较简单,如果只有一个bucket则可以把配置写入config.php里,内容如下
'FILE_UPLOAD_TYPE' => 'Oss',
'UPLOAD_TYPE_CONFIG' => array(
    'access_id' => 'access_id', //阿里云Access Key ID
    'access_key' => 'access_key', //阿里云Access Key Secret
    'bucket' => 'bucket' //阿里云的bucket
),

如果你需要将不同的文件存入不同的bucket则需要在上传方法中采用动态配置
$config     = array(
    'maxSize'  => 0,
    'exts'     => array('jpg', 'jpeg', 'png'),
    'saveName' => array('uniq_photo_name', '__FILE__'),
    'rootPath' => '/',
);
$oss_config = array(
    'access_id'  => 'access_id', //阿里云Access Key ID
    'access_key' => 'access_key', //阿里云Access Key Secret
    'bucket'     => 'bucket'
);
$upload     = new \Think\Upload($config, 'Oss', $oss_config);



展开
收起
anerg 2014-12-19 17:04:33 20277 0
5 条回答
写回答
取消 提交回答
  • Re用于ThinkPHP3.2的阿里云OSS轻量级驱动
    上传图片的TP那个代码怎么写的啊? 我用TP自带的上传代码,上传不上去,地址不对....................请问,上传到OOS  是怎么填上传地址的?

    -------------------------

    Re用于ThinkPHP3.2的阿里云OSS轻量级驱动
    请问,用TP自带的那个上传,该怎么写?
                    $upload = new \Think\Upload();                              // 实例化上传类
            $upload->maxSize   =   3145728;                          // 设置附件上传大小  
            $upload->exts      =   array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型  
            $upload->rootPath  =   'http://kepei-2.oss-cn-shenzhen.aliyuncs.com/2016/test/';
            $upload->savePath  =   '';                       // 设置附件上传目录  
            $upload->autoSub   =   false;                              //是否开启子目录保存图片形式
            $upload->saveName  =   array('uniqid','');                  //文件上传保存名称    
            $info   =   $upload->upload();  
    2016-04-26 11:36:11
    赞同 展开评论 打赏
  • Re用于ThinkPHP3.2的阿里云OSS轻量级驱动
    额,怎么上传不了啊
    2015-08-10 12:07:34
    赞同 展开评论 打赏
  • Re用于ThinkPHP3.2的阿里云OSS轻量级驱动
    厉害,就需要这个
    2014-12-30 12:24:43
    赞同 展开评论 打赏
  • Re用于ThinkPHP3.2的阿里云OSS轻量级驱动
    enen  不错
    2014-12-22 14:14:45
    赞同 展开评论 打赏
  • Re用于ThinkPHP3.2的阿里云OSS轻量级驱动
    好牛的。

    but,别人也许需要更多的功能啊
    2014-12-22 09:49:50
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
OSS运维进阶实战手册 立即下载
《OSS运维基础实战手册》 立即下载
OSS运维基础实战手册 立即下载