隨著業務增長,公司原本存放在本地服務器的用戶頭像管理愈發吃力。為了統一資源管理、提升訪問速度,決定將所有本地頭像遷移至七牛雲存儲。本文將詳細記錄基於 PHP 實現「判斷存在 → 單個抓取 → 批量遷移」的完整技術方案,供有類似需求的開發者參考。
整個遷移流程可拆解為三個步驟:
Fetch API 將遠程圖片拉取入桶。利用七牛 PHP SDK 的 Qiniu_RS_Stat 接口,根據文件 Key 獲取元信息;若返回錯誤則視為不存在。
/**
* 檢查七牛雲文件是否存在
* @param string $url 七牛文件完整 URL
* @return bool
*/
function url_exists($url) {
require_once(COMMON_PATH . "qiniu/rs.php");
require_once(COMMON_PATH . "qiniu/http.php");
$parts = parse_url($url);
$bucket = 'your_bucket_name'; // 替換為你的空間名
$key = substr($parts['path'], 1); // 去除開頭 "/"
$accessKey = 'your_access_key'; // 替換為你的 AK
$secretKey = 'your_secret_key'; // 替換為你的 SK
Qiniu_SetKeys($accessKey, $secretKey);
$client = new Qiniu_MacHttpClient(null);
list($ret, $err) = Qiniu_RS_Stat($client, $bucket, $key);
return $err === null;
}
結合 url_exists 與本地 file_exists 雙重校驗,調用 Qiniu_RS_Fetch 將遠程圖片「搬運」到七牛,失敗時記錄錯誤日誌便於後續排查。
/**
* 抓取單個遠程頭像到七牛
* @param string $remotePath 本地服務器物理路徑
* @param string $qiniuPath 七牛目標文件 URL
*/
function oneFetch($remotePath, $qiniuPath) {
if (!url_exists($qiniuPath) && file_exists($remotePath)) {
require_once(COMMON_PATH . "qiniu/rs.php");
require_once(COMMON_PATH . "qiniu/http.php");
require_once(COMMON_PATH . "qiniu/conf.php");
$client = new Qiniu_MacHttpClient(null);
$accessUrl = 'https://your-domain.com/' . $remotePath; // 公開可訪問的遠程地址
$bucket = 'your_bucket_name';
$key = basename($qiniuPath); // 七牛存儲文件名
$ret = Qiniu_RS_Fetch($client, $accessUrl, $bucket, $key);
if ($ret === null) {
// 記錄失敗 Key,方便人工介入
file_put_contents('fail.log', $key . "\n", FILE_APPEND);
} else {
var_dump($ret); // 成功返回文件元信息
}
} else {
echo '頭像已存在或本地文件缺失:' . $qiniuPath . '
';
}
}
採用 LIMIT offset, size 分頁查詢,每次處理 10 條記錄,通過 header("Location: ...") 實現頁面自動跳轉繼續下一批,並配合 ob_flush() flush() 實時輸出進度。
function batchMigrate() {
header("Content-type: text/html; charset=utf-8");
set_time_limit(0);
$start = isset($_GET['num']) ? intval($_GET['num']) : 0;
$limit = 10;
// 建議改用 mysqli / PDO,此處保留原邏輯示意
$link = mysqli_connect("localhost", "root", "root", "test");
mysqli_set_charset($link, "utf8");
$sql = "SELECT remotePath, qiniuPath FROM avatars ORDER BY id LIMIT {$start}, {$limit}";
$result = mysqli_query($link, $sql);
if (mysqli_num_rows($result)) {
while ($row = mysqli_fetch_assoc($result)) {
oneFetch($row['remotePath'], $row['qiniuPath']);
}
$next = $start + $limit;
echo "已處理 {$next} 條記錄
";
// 自動跳轉下一批
header("Refresh:2; url=?num={$next}");
} else {
echo '遷移完成!共處理 ' . $start . ' 條記錄。';
}
mysqli_close($link);
}
// 入口調用
batchMigrate();
fail.log 記錄的失敗 Key,編寫腳本二次重試,或人工排查來源鏈接是否失效。通過上述方案,我們成功將數萬條本地頭像平滑遷移至七牛雲,顯著降低了本地存儲壓力,並借助 CDN 加速提升了用戶端加載體驗。希望這份實戰記錄能為你的遷移項目提供參考。