Files
ReinLoopTest/ControlPanel/server-client.js
T

81 lines
2.8 KiB
JavaScript

const fs = require("node:fs");
const path = require("node:path");
const { Readable } = require("node:stream");
const { pipeline } = require("node:stream/promises");
const DOWNLOAD_DIR = path.resolve(process.env.DOWNLOAD_DIR || "downloads");
function getServerCredentials(options = {}) {
const apiUrl = options.apiUrl || process.env.REINLOOP_API_URL;
const adminToken = options.adminToken || process.env.B_ADMIN_TOKEN;
if (!apiUrl) throw new Error("缺少 server API URL");
if (!adminToken) throw new Error("缺少 Admin Token");
return { apiUrl, adminToken };
}
async function callServer(payload, options = {}) {
const { apiUrl, adminToken } = getServerCredentials(options);
const response = await fetch(apiUrl, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ ...payload, adminToken })
});
let result = null;
try {
result = await response.json();
} catch {
result = null;
}
if (!response.ok) {
const message = result && typeof result.errMsg === "string" && result.errMsg
? result.errMsg
: `server 请求失败: HTTP ${response.status}`;
throw new Error(message);
}
if (!result || typeof result !== "object") {
throw new Error("server 返回格式无效");
}
if (!result.success) throw new Error(result.errMsg || "server 返回失败");
return result;
}
function downloadHeaders(options = {}) {
if (!options.adminToken) return {};
return {
authorization: `Bearer ${options.adminToken}`,
"x-admin-token": options.adminToken
};
}
async function downloadFromUrl(url, fileName, options = {}) {
await fs.promises.mkdir(DOWNLOAD_DIR, { recursive: true });
return downloadToPath(url, path.join(DOWNLOAD_DIR, path.basename(fileName)), options);
}
async function downloadToPath(url, destination, options = {}) {
const response = await fetch(url, { headers: downloadHeaders(options) });
if (!response.ok || !response.body) {
throw new Error(`下载失败: HTTP ${response.status}`);
}
await fs.promises.mkdir(path.dirname(destination), { recursive: true });
const temporary = `${destination}.downloading`;
try {
await pipeline(Readable.fromWeb(response.body), fs.createWriteStream(temporary));
await fs.promises.rename(temporary, destination);
} catch (error) {
await fs.promises.rm(temporary, { force: true });
throw error;
}
console.log(`[${new Date().toISOString()}] 已下载: ${destination}`);
return destination;
}
async function downloadFile(fileID, fileName, options = {}) {
const { url } = await callServer({ type: "downloadModel", fileID }, options);
return downloadFromUrl(url, fileName, options);
}
module.exports = { callServer, downloadFile, downloadFromUrl, downloadToPath, getServerCredentials };