guanghulab/scripts/bridge/upload-pdf.js
2026-05-10 13:12:44 +08:00

182 lines
6.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// scripts/bridge/upload-pdf.js
// 🌉 桥接·PDF 上传
//
// 将生成的 PDF 文件上传到可下载位置
// 支持多种上传方式:
// 方案A阿里云 OSS国内快
// 方案BGitHub Release Assets
// 方案C服务器目录/var/www/guanghulab/broadcasts/
//
// 环境变量:
// PDF_MANIFEST pdf-manifest.json 路径
// UPLOAD_MODE 上传模式: oss | github | server默认 server
// OSS_ACCESS_KEY 阿里云 OSS AccessKey
// OSS_SECRET_KEY 阿里云 OSS SecretKey
// OSS_BUCKET 阿里云 OSS Bucket
// OSS_REGION 阿里云 OSS Region
// SERVER_BROADCAST_DIR 服务器广播目录
'use strict';
const fs = require('fs');
const path = require('path');
const OUTPUT_DIR = path.join('data', 'broadcasts', 'pdf');
const SITE_BASE_URL = 'https://guanghulab.com';
// ══════════════════════════════════════════════════════════
// 上传模式
// ══════════════════════════════════════════════════════════
/**
* 服务器本地模式:复制 PDF 到指定目录
*/
async function uploadToServer(pdfFiles) {
const serverDir = process.env.SERVER_BROADCAST_DIR ||
'/var/www/guanghulab/broadcasts';
// 在 CI 环境中,只记录路径(不实际复制)
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
console.log(`☁️ 服务器模式 · 目标目录: ${serverDir}`);
const results = [];
for (const item of pdfFiles) {
const pdfPath = item.pdf;
if (!pdfPath || !fs.existsSync(pdfPath)) {
console.log(` ⚠️ PDF 不存在: ${pdfPath}`);
continue;
}
const filename = path.basename(pdfPath);
const destPath = path.join(serverDir, filename);
const downloadUrl = `${SITE_BASE_URL}/broadcasts/${filename}`;
if (isCI) {
// CI 环境:仅记录,由部署脚本负责实际复制
results.push({ ...item, download_url: downloadUrl });
console.log(` 📋 ${filename}${downloadUrl} (CI模式·待部署)`);
} else {
try {
if (!fs.existsSync(serverDir)) {
fs.mkdirSync(serverDir, { recursive: true });
}
fs.copyFileSync(pdfPath, destPath);
results.push({ ...item, download_url: downloadUrl });
console.log(`${filename}${destPath}`);
} catch (e) {
console.error(` ❌ 复制失败: ${filename}: ${e.message}`);
}
}
}
return results;
}
/**
* GitHub 模式:将 PDF 提交到仓库(已在 data/broadcasts/pdf/ 中)
*/
async function uploadToGitHub(pdfFiles) {
console.log(`☁️ GitHub 模式 · PDF 已在仓库 data/broadcasts/pdf/ 中`);
const results = [];
for (const item of pdfFiles) {
const pdfPath = item.pdf;
if (!pdfPath || !fs.existsSync(pdfPath)) continue;
const filename = path.basename(pdfPath);
const downloadUrl = `https://github.com/qinfendebingshuo/guanghulab/raw/main/${pdfPath}`;
results.push({ ...item, download_url: downloadUrl });
console.log(`${filename}${downloadUrl}`);
}
return results;
}
/**
* OSS 模式:上传到阿里云 OSS需安装 ali-oss SDK
*/
async function uploadToOSS(pdfFiles) {
const accessKey = process.env.OSS_ACCESS_KEY;
const secretKey = process.env.OSS_SECRET_KEY;
const bucket = process.env.OSS_BUCKET || 'guanghulab-broadcasts';
const region = process.env.OSS_REGION || 'oss-cn-shanghai';
if (!accessKey || !secretKey) {
console.log('⚠️ OSS 密钥未配置,回退到 GitHub 模式');
return uploadToGitHub(pdfFiles);
}
console.log(`☁️ OSS 模式 · Bucket: ${bucket} · Region: ${region}`);
let OSS;
try {
OSS = require('ali-oss');
} catch (e) {
console.log('⚠️ ali-oss 未安装,回退到 GitHub 模式');
return uploadToGitHub(pdfFiles);
}
const client = new OSS({ region, accessKeyId: accessKey, accessKeySecret: secretKey, bucket });
const results = [];
for (const item of pdfFiles) {
const pdfPath = item.pdf;
if (!pdfPath || !fs.existsSync(pdfPath)) continue;
const filename = path.basename(pdfPath);
const ossKey = `broadcasts/${filename}`;
try {
const result = await client.put(ossKey, pdfPath);
results.push({ ...item, download_url: result.url });
console.log(`${filename}${result.url}`);
} catch (e) {
console.error(` ❌ OSS 上传失败: ${filename}: ${e.message}`);
}
}
return results;
}
// ══════════════════════════════════════════════════════════
// 主逻辑
// ══════════════════════════════════════════════════════════
async function main() {
const manifestFile = process.env.PDF_MANIFEST ||
path.join(OUTPUT_DIR, 'pdf-manifest.json');
if (!fs.existsSync(manifestFile)) {
console.log('📭 无 pdf-manifest.json跳过上传');
process.exit(0);
}
const pdfFiles = JSON.parse(fs.readFileSync(manifestFile, 'utf8'));
if (pdfFiles.length === 0) {
console.log('📭 PDF 列表为空,跳过上传');
process.exit(0);
}
const mode = (process.env.UPLOAD_MODE || 'server').toLowerCase();
console.log(`🌉 PDF 上传 · 模式: ${mode} · 共 ${pdfFiles.length}`);
let results;
switch (mode) {
case 'oss': results = await uploadToOSS(pdfFiles); break;
case 'github': results = await uploadToGitHub(pdfFiles); break;
case 'server':
default: results = await uploadToServer(pdfFiles); break;
}
// 写入分发清单
const distManifest = path.join(OUTPUT_DIR, 'dist-manifest.json');
fs.writeFileSync(distManifest, JSON.stringify(results, null, 2));
console.log(`\n✅ 上传完成 · ${results.length} 份 · 清单: ${distManifest}`);
if (process.env.GITHUB_OUTPUT) {
fs.appendFileSync(process.env.GITHUB_OUTPUT,
`uploaded_count=${results.length}\ndist_manifest=${distManifest}\n`
);
}
}
main().catch(e => { console.error(e); process.exit(1); });