| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- // 列 OSS audio/ 下,按月分桶,看每个月的 key 模式分布
- const fs = require('fs');
- const path = require('path');
- const envTxt = fs.readFileSync(path.join(__dirname, '..', '..', 'server', '.env.production'), 'utf8');
- const env = {};
- for (const line of envTxt.split(/\r?\n/)) {
- const m = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*)\s*$/);
- if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, '');
- }
- const OSS = require(path.join(__dirname, '..', '..', 'server', 'node_modules', 'ali-oss'));
- const client = new OSS({ accessKeyId: env.OSS_ACCESS_KEY_ID, accessKeySecret: env.OSS_ACCESS_KEY_SECRET, bucket: 'rrbrr-book-audio', endpoint: 'oss-cn-shanghai.aliyuncs.com', secure: true });
- async function listAll(prefix) {
- const all = [];
- let marker = null;
- do {
- const r = await client.list({ prefix, 'max-keys': 1000, marker });
- all.push(...(r.objects || []));
- marker = r.nextMarker || null;
- } while (marker);
- return all;
- }
- function fmt(b) { return (b/1024/1024).toFixed(1) + ' MB'; }
- (async () => {
- const all = await listAll('audio/');
- // 按月 + key pattern 分类
- const byMonthPattern = new Map();
- for (const o of all) {
- const m = (o.lastModified || '').slice(0, 7); // YYYY-MM
- const key = o.name;
- // 提取关键模式
- let pattern;
- if (key.startsWith('audio/merged/')) pattern = 'audio/merged/...';
- else {
- const parts = key.split('/');
- const second = parts[1] || '';
- if (second.startsWith('preview-')) pattern = 'audio/preview-uuid/...';
- else if (second.startsWith('sync-')) pattern = 'audio/sync-uuid/...';
- else if (/^[0-9a-f-]{36}$/.test(second)) {
- const fname = parts[2] || '';
- if (fname.includes('_merged')) pattern = 'audio/uuid/{uuid}_merged.{ext}';
- else if (fname.includes('output')) pattern = 'audio/uuid/output.{ext}';
- else if (fname.includes('cloud_segment')) pattern = 'audio/uuid/cloud_segment_*.{ext}';
- else pattern = `audio/uuid/${fname.split('.')[0]}.{ext}`;
- } else if (/^\d+$/.test(second)) pattern = 'audio/{numeric}/...'; // 比如 chapterId?
- else pattern = `audio/${second.substring(0,20)}/...`;
- }
- const k = `${m}|${pattern}`;
- const cur = byMonthPattern.get(k) || { count: 0, bytes: 0 };
- cur.count++; cur.bytes += o.size || 0;
- byMonthPattern.set(k, cur);
- }
- // 按月输出
- const months = [...new Set([...byMonthPattern.keys()].map(k => k.split('|')[0]))].sort();
- for (const mo of months) {
- console.log(`\n=== ${mo} ===`);
- const arr = [...byMonthPattern.entries()].filter(([k]) => k.startsWith(mo)).sort((a, b) => b[1].bytes - a[1].bytes);
- for (const [k, v] of arr) {
- const pat = k.split('|')[1];
- console.log(` ${String(v.count).padStart(7)} ${fmt(v.bytes).padStart(10)} ${pat}`);
- }
- }
- })();
|