69 lines
2.5 KiB
JavaScript
69 lines
2.5 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 })
|
|
});
|
|
if (!response.ok) throw new Error(`server 请求失败: HTTP ${response.status}`);
|
|
|
|
const result = await response.json();
|
|
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 }; |