這個(gè)需求是由于公司里對(duì)某個(gè)空間誤設(shè)置了生命周期谋减,隨著時(shí)間流逝很多文件請(qǐng)求不到了艇肴,關(guān)了生命周期后激蹲,之前賦予過(guò)生命周期的那些文件還是會(huì)把流程走下去棉磨,所以在穩(wěn)定后需要做一次數(shù)據(jù)的搬遷。
修改的方式有幾種:
第一種是七牛提供了可視化操作工具学辱,可以讓沒(méi)有開(kāi)發(fā)經(jīng)驗(yàn)的人也能做修改乘瓤,但按我同事的說(shuō)法是很卡很卡難以操作(因?yàn)槲覀冞@個(gè)空間文件數(shù)挺多的,大概百萬(wàn)的文件數(shù))策泣,我沒(méi)有去嘗試
第二種是七牛提供的qshell指令衙傀,具體文檔 https://developer.qiniu.com/kodo/1302/qshell ,我沒(méi)有使用這個(gè)的原因是萨咕,淺試了一下可以實(shí)現(xiàn)需求统抬,但是list導(dǎo)出的文件列表格式和解凍、修改存儲(chǔ)類型時(shí)導(dǎo)入文件需要的格式有差別任洞,實(shí)際跑的時(shí)候那么大量的數(shù)據(jù)要手改的話不現(xiàn)實(shí)(但是qshell的list好的地方是可以filter文件存儲(chǔ)狀態(tài)和時(shí)間蓄喇,可以快速導(dǎo)出你具體想找的文件列表)
把試用的命令貼出來(lái)以供參考:
// 導(dǎo)出列表
sudo ./qshell listbucket2 --start 2022-10-10 --end 2022-10-12 --storages 2 --show-fields Key,StorageType as-prod -o list.txt
// 批量解凍7天
./qshell batchrestorear as-prod 7 -i list.txt
// 批量修改存儲(chǔ)類型
./qshell batchchtype as-prod -i list.txt
第三種是我現(xiàn)在使用的方式发侵,node sdk
文檔:https://developer.qiniu.com/kodo/1289/nodejs
本地起一個(gè)koa的服務(wù)交掏,安裝七牛提供的nodesdk庫(kù),按照文檔配置auth刃鳄,listPrefix的參數(shù)沒(méi)有看到日期盅弛、當(dāng)前存儲(chǔ)類型之類的filter,我目前就只能把整個(gè)空間遍歷一遍叔锐,找到歸檔的文件先解凍挪鹏,由于解凍需要時(shí)間,所以先跑一遍做解凍愉烙,再跑一遍做存儲(chǔ)類型修改讨盒,整體比較耗時(shí)間。
下面是具體的代碼步责,解凍和修改兩個(gè)步驟寫一起了返顺,用的時(shí)候自己切換下注釋禀苦,我圖省力直接放在根路由下操作了,記得把代碼改好了再打開(kāi)服務(wù)遂鹊。
const router = require('koa-router')()
const qiniu = require('qiniu')
const {logger} = require('../logs');
// 配置你的auth相關(guān)信息
const mac = new qiniu.auth.digest.Mac(xxx, xxx);
const config = new qiniu.conf.Config();
config.zone = qiniu.zone.Zone_z0;
const bucketManager = new qiniu.rs.BucketManager(mac, config);
router.get('/', async (ctx, next) => {
limitList(null, true);
await ctx.render('index', {
title: 'Hello Koa 2!'
})
})
// 你的空間名
const bucket = 'xxxbucket';
let count = 0;
let restoreCount = 0;
function limitList(marker, isFirst) {
if (!isFirst) {
if (!marker) {
logger.error('無(wú)marker振乏,結(jié)束!1恕;塾省!V勐健误澳!共執(zhí)行個(gè)數(shù):' + restoreCount);
return
}
}
const options = { limit: 1000 };
if (marker) {
options['marker'] = marker;
}
bucketManager.listPrefix(bucket, options, (err, res) => {
if (!err) {
const marker = res.marker;
const data = res.items;
for (let i = 0; i < data.length; i++) {
const fileItem = data[i];
// 0標(biāo)準(zhǔn) 1低頻 2歸檔
if (fileItem.type === 2) {
// 用于修改文件存儲(chǔ)類型
// bucketManager.changeType(bucket, fileItem.key, 0, (e) => {
// if (e) {
// logger.error('類型修改失敗:' + fileItem.key + JSON.stringify(e));
// } else {
// restoreCount++;
// logger.info('類型修改成功:' + fileItem.key);
// }
// })
// 用于解凍
const entry = bucket + ":" + fileItem.key;
bucketManager.restoreAr(entry, 7, (e) => {
if (e) {
logger.error('執(zhí)行解凍失斍厍:' + entry + JSON.stringify(e));
} else {
restoreCount++;
logger.info('執(zhí)行解凍:' + entry);
}
})
}
}
count += 1000;
logger.info('---------已經(jīng)遍歷條目數(shù)量:' + count + '執(zhí)行成功數(shù)量:' + restoreCount + '---------');
limitList(marker, false)
} else {
console.log('error:' + err)
}
})
}
module.exports = router