126 lines
3.8 KiB
JavaScript
126 lines
3.8 KiB
JavaScript
import axios from 'axios';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
const JINGROW_SERVER_URL = process.env.JINGROW_SERVER_URL;
|
|
const PUBLIC_FILES_DIR = path.join(process.cwd(), 'public/files');
|
|
|
|
if (!fs.existsSync(PUBLIC_FILES_DIR)) {
|
|
fs.mkdirSync(PUBLIC_FILES_DIR, { recursive: true });
|
|
}
|
|
|
|
async function downloadToLocal(fileUrl) {
|
|
try {
|
|
let fullUrl = fileUrl;
|
|
if (!/^https?:\/\//.test(fileUrl)) {
|
|
fullUrl = `${JINGROW_SERVER_URL}${fileUrl}`;
|
|
}
|
|
const fileName = path.basename(fullUrl.split('?')[0]);
|
|
const localPath = path.join(PUBLIC_FILES_DIR, fileName);
|
|
const localUrl = `/files/${fileName}`;
|
|
if (!fs.existsSync(localPath)) {
|
|
const response = await axios.get(fullUrl, { responseType: 'stream' });
|
|
await new Promise((resolve, reject) => {
|
|
const writer = fs.createWriteStream(localPath);
|
|
response.data.pipe(writer);
|
|
writer.on('finish', resolve);
|
|
writer.on('error', reject);
|
|
});
|
|
}
|
|
return localUrl;
|
|
} catch (e) {
|
|
return fileUrl;
|
|
}
|
|
}
|
|
|
|
// 提取富文本中的所有图片链接
|
|
function extractImageUrlsFromHtml(html) {
|
|
if (!html) return [];
|
|
const regex = /<img[^>]+src=["']([^"'>]+)["']/g;
|
|
const urls = [];
|
|
let match;
|
|
while ((match = regex.exec(html)) !== null) {
|
|
urls.push(match[1]);
|
|
}
|
|
return urls;
|
|
}
|
|
|
|
// 替换富文本中的图片链接为本地路径
|
|
async function replaceImageUrlsInHtml(html) {
|
|
if (!html) return html;
|
|
const regex = /<img([^>]+)src=["']([^"'>]+)["']/g;
|
|
return await html.replace(regex, async (match, pre, url) => {
|
|
const localUrl = await downloadToLocal(url);
|
|
return `<img${pre}src="${localUrl}"`;
|
|
});
|
|
}
|
|
|
|
export async function POST(request) {
|
|
try {
|
|
const body = await request.json();
|
|
const slug_list = body.slug_list;
|
|
const page = body.page || 1;
|
|
const page_size = body.page_size || undefined;
|
|
if (!Array.isArray(slug_list)) {
|
|
return Response.json({ error: 'slug_list参数必须为数组' }, { status: 400 });
|
|
}
|
|
const params = { slug_list: JSON.stringify(slug_list), page };
|
|
if (page_size) params.page_size = page_size;
|
|
const response = await axios.get(
|
|
`${JINGROW_SERVER_URL}/api/method/jsite.api.v1.get_page_data`,
|
|
{ params }
|
|
);
|
|
const message = response.data.message;
|
|
let data = message?.data;
|
|
if (Array.isArray(data)) {
|
|
for (const item of data) {
|
|
if (item.image) {
|
|
item.image = await downloadToLocal(item.image);
|
|
}
|
|
for (const key of ['content', 'additional_content']) {
|
|
if (item[key]) {
|
|
const urls = extractImageUrlsFromHtml(item[key]);
|
|
let html = item[key];
|
|
for (const url of urls) {
|
|
const localUrl = await downloadToLocal(url);
|
|
html = html.replaceAll(url, localUrl);
|
|
}
|
|
item[key] = html;
|
|
}
|
|
}
|
|
}
|
|
} else if (data) {
|
|
if (data.image) {
|
|
data.image = await downloadToLocal(data.image);
|
|
}
|
|
for (const key of ['content', 'additional_content']) {
|
|
if (data[key]) {
|
|
const urls = extractImageUrlsFromHtml(data[key]);
|
|
let html = data[key];
|
|
for (const url of urls) {
|
|
const localUrl = await downloadToLocal(url);
|
|
html = html.replaceAll(url, localUrl);
|
|
}
|
|
data[key] = html;
|
|
}
|
|
}
|
|
}
|
|
if (message?.data) {
|
|
return Response.json({
|
|
data: message.data,
|
|
total: message.total,
|
|
page_info: message.page_info
|
|
});
|
|
} else if (message?.error) {
|
|
return Response.json({ error: message.error }, { status: 400 });
|
|
} else {
|
|
return Response.json({ error: '未知错误' }, { status: 500 });
|
|
}
|
|
} catch (error) {
|
|
return Response.json(
|
|
{ error: error.message, detail: error?.response?.data || null },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|