ThinkPHP5+七牛云文件操作 方法梳理

  • 背景
    近期在项目的优化过程中,注意到对七牛云存储的使用频率提高了
    同时为了减轻对项目资源服务器的流量压力
    选择将常用的图片、word 文件转储到七牛云服务器
    在此根据自己的使用经验,梳理一下核心方法的处理,方便大家的参考使用 …

官方文档 - 【七牛云 php-SDK】


前期处理

  • composer 安装
  php composer.phar require qiniu/php-sdk

实现方法

根据项目需求,在此整理几个核心的操作方法

1. 抓取 web上的图片,上传七牛云服务器

  • 示例:
    $save_path = 'uploads/'.date('Ymd',time()).'/'.microtime(true).'.png';
	/**
     * 抓取 web上的图片,上传七牛云服务器
     * @param $imgUrl web 图片地址
     * @param string $saveImgPath 保存到七牛云的地址
     * @return string
     */
    public function uploadWebImgToQiniu($imgUrl,$saveImgPath = '')
    {
        #读取网上图片内容
        $imageData = self::getSslPage($imgUrl);
        $auth  = new Auth($this->accessKey, $this->secretKey);
        $token = $auth->uploadToken($this->bucket);
        $key   = $saveImgPath;

        $up    = new UploadManager();
        $mime  = 'image/jpeg';
        list($rest, $err) = $up->put($token, $key, $imageData, null, $mime);
        if ($err) {
            return '';
        } else {
            $host = config('cdn.Host');
            return $host.'/'.$rest['key'];
        }
    }
    
    /**
     * 抓取网上图片 web image
     * @param $url
     * @return bool|string
     */
    public function getSslPage($url) {
        if(!empty($slika)){
            file_put_contents('vest1.webp', $slika);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_REFERER, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

2. 将服务器上的文件 上传到七牛云服务器

  • 场景:以我们的实际项目为例,对用户的订单审核通过后,会生成一份 word文件
    然后上传的七牛云,数据表中会记录下文件地址
    方便后期,直接下载查看
    /**
     * 将服务器上的文件 上传到七牛云服务器
     * @param string $file_name
     * @param string $file_from_path
     * @param string $file_to_path
     * @param string $ext_name
     * @return mixed|string
     * @throws Exception
     */
    private function uploadServerFileToQiniu($file_name = '',$file_from_path = '',$file_to_path = '',$ext_name = 'txt')
    {
        $auth = $this->getQiniuAuth();
        // 生成上传Token
        $token = $auth->uploadToken($this->bucket);
        // 构建 UploadManager 对象
        $uploadMgr = new UploadManager();
        // 上传文件到七牛
        if (empty($file_name)){
            $file_name = md5(uniqid(microtime(true),true));
        }

        if (empty($file_to_path)){}

        $key = $file_to_path.'/'.$file_name.'.'.$ext_name;


        list($ret, $err) = $uploadMgr->putFile($token, $key, $file_from_path);
        if ($err !== null) {
            //上传失败
            return '';
        } else {
            //删除临时服务器 文件
            unlink($file_from_path);
            return $ret['key'];
        }
    }

3. 删除七牛云上的文件

  • 应用场景:比如存储了用户上传的头像信息,那么前期被替换的头像,就没必要保存了
    可以将原先的头像地址记录到数据表
    编写计划任务,每天删除一下无效的文件
/**
     * 删除文件
     * @param string $file_key
     * @return int 1:删除成功 ,0:删除失败
     */
    public function deleteQiniuFile($file_key = ''){
        $auth = new Auth($this->accessKey, $this->secretKey);
        $config = new \Qiniu\Config();
        $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
        $err = $bucketManager->delete($this->bucket, $file_key);
        if ($err) {
            return 0;
        }else{
            return 1;
        }
    }

4. 将七牛云中的多个文件,压缩包存储

  • 场景:七牛云服务器中已存储了多个 word 稿件文本
    此时需要将这些文本压缩为一个 .rar 文件,方便运营人员一次性下载
    调用该方法, 记录生成的 压缩文件链接
    /**
     * 生成word稿件压缩包
     * @param string $task_idstr
     * @param int $index
     * @param array $picture_arr
     * @return array
     */
    public function createWordFileRar($task_idstr = '',$index = 1,$picture_arr = []){

        $zipKey = "task_words/{$task_idstr}_{$index}.zip";

        //组装七牛云请求参数
        $fops = 'mkzip/2';
        //每十个文件,作为一个压缩包

        foreach ($picture_arr as $key_ => $val) {
            //添加图片重命名
            $fops .= '/url/'.\Qiniu\base64_urlSafeEncode($val);
        }
        $key = $this->fileKey;  //mode = 2时,仅仅为符合pfop操作的接口规格而存在,并没有实际的意义,但需要是操作空间中存在的资源的 key

        $fops .= '|saveas/' . \Qiniu\base64_urlSafeEncode("$this->bucket:$zipKey");
        $result = $this->picMkzip($key, $fops);
        $result['qiniu_url'] = $zipKey;

        return $result;
    }

附录

根据业务开发过程中遇到的问题,在此做下梳理,方便大家避雷

问题1 . 七牛云文件上传延时

  • 当调用七牛云上传文件接口时,可能会出现一种情况:
场景描述:
	我指定要存储的压缩文件名为 'hello-1122337.rar';
	当数据发生变动后,我先删除这个文件,然后再重新生成一份,如此一来压缩文件的名称就没必要变动了
	但是我发现,执行逻辑后的压缩文件并不是最新的!

	另一种情况,我要生成的压缩文件较大(500M左右)
	测试生成时间要6~10秒
	我想每两秒去检查下是否生成完毕
	结果参考使用了网上很多的 判断web文件是否存在的方法
	即便实际情况6秒生成(七牛云后台都能看到文件了,甚至可以下载),但是检测方法直到20秒后才判断生成了
	这显然不能满足我的业务需求

问题分析:

  1. 七牛云服务器对同名文件有缓存,实际上并不会真实删除,当检测到文件同名时对已删除文件有复原的处理(猜测)
  2. 或者网上的判断文件是否存在的方法存在bug (排除,毕竟不可能都错吧)
  3. 本地设计的 while 循环判断时,同一个方法的调用存在缓存情况 (极有可能)
  • 解决方案
    回想以前的开发经验,在读取 html 页面时,后面添加个随机字符串就会避免缓存
    所以,在检查文件是否存在时,
    每次对文件路径加一个随机数,避免与前面的链接相同
    发现,顺利的解决的判断需求

    代码截图如下:

ThinkPHP5+七牛云文件操作 方法梳理_第1张图片

  • 补充一下 curl 检测图片资源方法
/**
 * php使用 curl 判断404
 * @param string $url
 * @return bool
 */
function check_url($url = ''){
    stream_context_set_default(
        array(
            'http' => array(
                'timeout' => 5,
            )
        )
    );
    $header = get_headers($url,1);
    if(strpos($header[0],'200')){
        return true;
    }
    if(strpos($header[0],'404')){
        return false;
    }
    if (strpos($header[0],'301') || strpos($header[0],'302')) {
        if(is_array($header['Location'])) {
            $redirectUrl = $header['Location'][count($header['Location'])-1];
        }else{
            $redirectUrl = $header['Location'];
        }
        return check_url($redirectUrl);
    }
}

你可能感兴趣的:(ThinkPHP,php,七牛云存储)