123 lines
3.8 KiB
JavaScript
123 lines
3.8 KiB
JavaScript
/**
|
|
* 把本地文件上传到 OSS `static/mini-user/`(不进小程序主包)。
|
|
* 凭证优先读 system_config,其次 server/dukang-api/.env。
|
|
*
|
|
* 用法:node scripts/upload-mini-user-static.mjs <localFile> [objectName]
|
|
*/
|
|
import { readFileSync, existsSync } from 'node:fs';
|
|
import { basename, resolve, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { createRequire } from 'node:module';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = resolve(__dirname, '..');
|
|
const apiRoot = resolve(root, 'server/dukang-api');
|
|
const require = createRequire(resolve(apiRoot, 'package.json'));
|
|
const OSS = require('ali-oss');
|
|
const { PrismaClient } = require('@prisma/client');
|
|
|
|
function loadEnvFile(path) {
|
|
if (!existsSync(path)) return;
|
|
for (const line of readFileSync(path, 'utf8').split(/\r?\n/)) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
const eq = trimmed.indexOf('=');
|
|
if (eq <= 0) continue;
|
|
const key = trimmed.slice(0, eq).trim();
|
|
let value = trimmed.slice(eq + 1).trim();
|
|
if (
|
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
(value.startsWith("'") && value.endsWith("'"))
|
|
) {
|
|
value = value.slice(1, -1);
|
|
}
|
|
if (process.env[key] === undefined) process.env[key] = value;
|
|
}
|
|
}
|
|
|
|
loadEnvFile(resolve(apiRoot, '.env'));
|
|
loadEnvFile(resolve(apiRoot, '.env.local'));
|
|
|
|
const localFile = process.argv[2];
|
|
if (!localFile) {
|
|
console.error('用法:node scripts/upload-mini-user-static.mjs <localFile> [objectName]');
|
|
process.exit(1);
|
|
}
|
|
const absFile = resolve(process.cwd(), localFile);
|
|
if (!existsSync(absFile)) {
|
|
console.error(`文件不存在:${absFile}`);
|
|
process.exit(1);
|
|
}
|
|
const objectName = process.argv[3] || basename(absFile);
|
|
const ossKey = `static/mini-user/${objectName.replace(/^\/+/, '')}`;
|
|
|
|
const prisma = new PrismaClient();
|
|
const rows = await prisma.systemConfig.findMany({
|
|
where: {
|
|
configKey: {
|
|
in: [
|
|
'OSS_ACCESS_KEY_ID',
|
|
'OSS_ACCESS_KEY_SECRET',
|
|
'OSS_BUCKET',
|
|
'OSS_REGION',
|
|
'OSS_ENDPOINT',
|
|
'OSS_CDN_BASE',
|
|
'OSS_AUTHORIZATION_V4',
|
|
'MINI_USER_STATIC_OSS_BASE',
|
|
],
|
|
},
|
|
},
|
|
});
|
|
await prisma.$disconnect();
|
|
|
|
for (const row of rows) {
|
|
if (row.value?.trim()) process.env[row.configKey] = row.value.trim();
|
|
}
|
|
|
|
const accessKeyId = process.env.OSS_ACCESS_KEY_ID ?? '';
|
|
const accessKeySecret = process.env.OSS_ACCESS_KEY_SECRET ?? '';
|
|
const bucket = process.env.OSS_BUCKET ?? '';
|
|
const region = process.env.OSS_REGION ?? 'oss-cn-hangzhou';
|
|
const endpoint = process.env.OSS_ENDPOINT ?? '';
|
|
const cdnBase = (process.env.OSS_CDN_BASE ?? '').replace(/\/$/, '');
|
|
const staticBase = (process.env.MINI_USER_STATIC_OSS_BASE ?? '').replace(/\/$/, '/');
|
|
|
|
if (!accessKeyId || !accessKeySecret || !bucket) {
|
|
console.error('OSS 未配置:请在 HQ 系统设置或 .env 填写 OSS_ACCESS_KEY_ID / SECRET / BUCKET');
|
|
process.exit(1);
|
|
}
|
|
|
|
const client = new OSS({
|
|
region,
|
|
accessKeyId,
|
|
accessKeySecret,
|
|
bucket,
|
|
...(endpoint ? { endpoint } : {}),
|
|
...(process.env.OSS_AUTHORIZATION_V4 === 'true' ? { authorizationV4: true } : {}),
|
|
});
|
|
|
|
const mime =
|
|
absFile.endsWith('.png')
|
|
? 'image/png'
|
|
: absFile.endsWith('.gif')
|
|
? 'image/gif'
|
|
: absFile.endsWith('.jpg') || absFile.endsWith('.jpeg')
|
|
? 'image/jpeg'
|
|
: 'application/octet-stream';
|
|
|
|
const result = await client.put(ossKey, absFile, {
|
|
mime,
|
|
headers: {
|
|
'Content-Disposition': 'inline',
|
|
'Cache-Control': 'public, max-age=31536000',
|
|
},
|
|
});
|
|
|
|
const publicUrl =
|
|
(staticBase ? `${staticBase}${objectName}` : '') ||
|
|
(cdnBase ? `${cdnBase}/${ossKey}` : result.url);
|
|
|
|
console.log(`uploaded bucket=${bucket} region=${region}`);
|
|
console.log(`key=${ossKey}`);
|
|
console.log(`url=${publicUrl}`);
|