重构 postProxy 函数,移动到新文件 ai-proxy-chunk/post-proxy.ts,优化文件上传处理逻辑

This commit is contained in:
2026-02-01 14:33:26 +08:00
parent 82c9b834e9
commit 32167faf67
2 changed files with 91 additions and 84 deletions

View File

@@ -0,0 +1,89 @@
import { IncomingMessage, ServerResponse } from 'http';
import busboy from 'busboy';
import { parseSearchValue } from '@kevisual/router/src/server/parse-body.ts';
import { pipeBusboy } from '../../pipe-busboy.ts';
import { ProxyOptions, getMetadata, getObjectName } from '../ai-proxy.ts';
export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts: ProxyOptions) => {
const _u = new URL(req.url, 'http://localhost');
const pathname = _u.pathname;
const oss = opts.oss;
const params = _u.searchParams;
const force = !!params.get('force');
const hash = params.get('hash');
const _fileSize: string = params.get('size');
let fileSize: number | undefined = undefined;
if (_fileSize) {
fileSize = parseInt(_fileSize, 10);
}
console.log('postProxy', { hash, force, fileSize });
let meta = parseSearchValue(params.get('meta'), { decode: true });
if (!hash && !force) {
return opts?.createNotFoundPage?.('no hash');
}
const { objectName, isOwner } = await getObjectName(req);
if (!isOwner) {
return opts?.createNotFoundPage?.('no permission');
}
const end = (data: any, message?: string, code = 200) => {
res.writeHead(code, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ code: code, data: data, message: message || 'success' }));
};
let statMeta: any = {};
if (!force) {
const check = await oss.checkObjectHash(objectName, hash, meta);
statMeta = check?.metaData || {};
let isNewMeta = false;
if (check.success && JSON.stringify(meta) !== '{}' && !check.equalMeta) {
meta = { ...statMeta, ...getMetadata(pathname), ...meta };
isNewMeta = true;
await oss.replaceObject(objectName, { ...meta });
}
if (check.success) {
return end({ success: true, hash, meta, isNewMeta, equalMeta: check.equalMeta }, '文件已存在');
}
}
const bb = busboy({
headers: req.headers,
limits: {
fileSize: 100 * 1024 * 1024, // 100MB
files: 1,
},
defCharset: 'utf-8',
});
let fileProcessed = false;
bb.on('file', async (name, file, info) => {
fileProcessed = true;
try {
await oss.putObject(
objectName,
file,
{
...statMeta,
...getMetadata(pathname),
...meta,
},
{ check: false, isStream: true },
);
end({ success: true, name, info, isNew: true, hash, meta: meta?.metaData, statMeta }, '上传成功', 200);
} catch (error) {
console.log('postProxy upload error', error);
end({ error: error }, '上传失败', 500);
}
});
bb.on('finish', () => {
// 只有当没有文件被处理时才执行end
if (!fileProcessed) {
end({ success: false }, '没有接收到文件', 400);
}
});
bb.on('error', (err) => {
console.error('Busboy 错误:', err);
end({ error: err }, '文件解析失败', 500);
});
pipeBusboy(req, res, bb);
};

View File

@@ -12,7 +12,7 @@ import { logger } from '@/modules/logger.ts';
import { pipeBusboy } from '../pipe-busboy.ts'; import { pipeBusboy } from '../pipe-busboy.ts';
import { pipeMinioStream } from '../pipe.ts'; import { pipeMinioStream } from '../pipe.ts';
import { Readable } from 'stream'; import { Readable } from 'stream';
import { postProxy } from './ai-proxy-chunk/post-proxy.ts'
type FileList = { type FileList = {
name: string; name: string;
prefix?: string; prefix?: string;
@@ -153,88 +153,6 @@ export const getMetadata = (pathname: string) => {
return meta; return meta;
}; };
export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts: ProxyOptions) => {
const _u = new URL(req.url, 'http://localhost');
const pathname = _u.pathname;
const oss = opts.oss;
const params = _u.searchParams;
const force = !!params.get('force');
const hash = params.get('hash');
const _fileSize: string = params.get('size');
let fileSize: number | undefined = undefined;
if (_fileSize) {
fileSize = parseInt(_fileSize, 10);
}
let meta = parseSearchValue(params.get('meta'), { decode: true });
if (!hash && !force) {
return opts?.createNotFoundPage?.('no hash');
}
const { objectName, isOwner } = await getObjectName(req);
if (!isOwner) {
return opts?.createNotFoundPage?.('no permission');
}
const end = (data: any, message?: string, code = 200) => {
res.writeHead(code, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ code: code, data: data, message: message || 'success' }));
};
let statMeta: any = {};
if (!force) {
const check = await oss.checkObjectHash(objectName, hash, meta);
statMeta = check?.metaData || {};
let isNewMeta = false;
if (check.success && JSON.stringify(meta) !== '{}' && !check.equalMeta) {
meta = { ...statMeta, ...getMetadata(pathname), ...meta };
isNewMeta = true;
await oss.replaceObject(objectName, { ...meta });
}
if (check.success) {
return end({ success: true, hash, meta, isNewMeta, equalMeta: check.equalMeta }, '文件已存在');
}
}
const bb = busboy({
headers: req.headers,
limits: {
fileSize: 100 * 1024 * 1024, // 100MB
files: 1,
},
defCharset: 'utf-8',
});
let fileProcessed = false;
bb.on('file', async (name, file, info) => {
fileProcessed = true;
try {
await oss.putObject(
objectName,
file,
{
...statMeta,
...getMetadata(pathname),
...meta,
},
{ check: false, isStream: true },
);
end({ success: true, name, info, isNew: true, hash, meta: meta?.metaData, statMeta }, '上传成功', 200);
} catch (error) {
console.log('postProxy upload error', error);
end({ error: error }, '上传失败', 500);
}
});
bb.on('finish', () => {
// 只有当没有文件被处理时才执行end
if (!fileProcessed) {
end({ success: false }, '没有接收到文件', 400);
}
});
bb.on('error', (err) => {
console.error('Busboy 错误:', err);
end({ error: err }, '文件解析失败', 500);
});
pipeBusboy(req, res, bb);
};
export const getObjectByPathname = (opts: { export const getObjectByPathname = (opts: {
pathname: string, pathname: string,
version?: string, version?: string,
@@ -377,7 +295,7 @@ export const renameProxy = async (req: IncomingMessage, res: ServerResponse, opt
} }
}; };
type ProxyOptions = { export type ProxyOptions = {
createNotFoundPage: (msg?: string) => any; createNotFoundPage: (msg?: string) => any;
oss?: OssBase; oss?: OssBase;
}; };