比如文件原来都存储在网站的upload目录,云存储网址是file.xxxx.com
首先配置nginx重写原图片地址到云存储地址,做302跳转
location ^~ /uploads/ {
if (!-e $request_filename) {
rewrite ^(/uploads/.*)$ https://file.xxx.com$1 permanent;
break;
}
}
然后使用同步工具,或者自己写个同步进程,在同步完后删除本地服务器图片
比如用WorkerMan+七牛SDK
use WorkermanWorker; use WorkermanTimer; use QiniuStorageUploadManager; use QiniuAuth; 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 QiniuHttpError && $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跳转有惩罚措施