比如文件原来都存储在网站的upload目录,云存储网址是file.xxxx.com

首先配置nginx重写原图片地址到云存储地址,做302跳转
location ^~ /uploads/ {
    if (!-e $request_filename) {
        rewrite ^(/uploads/.*)$ https://file.xxx.com$1 permanent;
        break;
    }
}

 

然后使用同步工具,或者自己写个同步进程,在同步完后删除本地服务器图片

比如用WorkerMan+七牛SDK

use Workerman\Worker;
use Workerman\Timer;
use Qiniu\Storage\UploadManager;
use Qiniu\Auth;

define('ROOT_PATH', realpath(__DIR__)); // 系统根目录
define('PUBLIC_PATH', ROOT_PATH . '/Public'); // 网站根目录
define('UPLOAD_PATH', ROOT_PATH . '/Public/uploads/'); // 上传文件磁盘目录
define('UPLOAD_URL', '/uploads/'); // 上传文件网址路径

$accessKey = ''; // 七牛accessKey
$secretKey = ''; // 七牛secretKey
$bucket = 'xxx'; // 存储空间

$worker1 = new Worker();
$worker1->count = 1;
$worker1->onWorkerStart = function ($worker) use ($accessKey, $secretKey, $bucket) {

    $workerId = $worker->id;

    // 毫秒级别
    Timer::add(60, function () use ($workerId, $accessKey, $secretKey, $bucket) {

        $uploadMgr = new UploadManager();

        $auth = new Auth($accessKey, $secretKey);

        $token = $auth->uploadToken($bucket);

        $files = dirTree(UPLOAD_PATH, true, true);

        $uploaded_count = 0;
        
        $count = count($files);

        foreach ($files as $file) {

            $url = str_replace(PUBLIC_PATH . '/', '', $file);
            
            if(strpos($url, 'qrcode')) {
                $count--;
                continue;
            }

            list($ret, $error) = $uploadMgr->putFile($token, str_replace(PUBLIC_PATH . '/', '', $file), $file);

            if ($ret && $ret['hash'] && $ret['key'] && $ret['key'] == $url) {
                $uploaded_count++;
                eol('文件已上传:' . $file);
                if (!unlink($file)) { // 删除本地文件
                    eol('清理本地文件失败:' . $file);
                }
            } else {
                if ($error instanceof Qiniu\Http\Error && $error->code() == 614) {
                    $uploaded_count++;
                    eol($error->message() . PHP_EOL . $file);
                    if (!unlink($file)) { // 删除本地文件
                        eol('清理本地文件失败:' . $file);
                    }
                }
                eol('文件上传失败:' . $file);
                eol($error);
            }
        }

        eol("总计文件:{$count},已上传:{$uploaded_count}");
    });
};

 



七牛同步和nginx防瞬时文件丢失原理:
后台端上传文件时,需要立马看到上传的文件,以便确认文件上传成功,且显示效果良好
而文件上传后的60s还在内本地服务器,所以nginx重写301跳转前判断文件存在,不会引发重写,返回给后台端的还是本地服务器上的文件
60s后,七牛同步Worker把文件同步到七牛,并删除本地文件,此时前台端读取文件,因为文件不存在,被nginx重写301到七牛

注意的时必须使用permanent(301跳转),否则rewrite结果是302临时跳转
302会导致浏览缓存之前的网址,百度也会缓存之前的网址,并于缓存过期后重新请求之前的网址
加重服务器和用户端浏览器负担,百度也对302跳转有惩罚措施

posted on 2021-07-07 09:31  lbnnbs  阅读(180)  评论(0编辑  收藏  举报