mirror of
https://github.com/labring/FastGPT.git
synced 2026-05-07 01:02:55 +08:00
fix(sandbox): xlsx/avi 等不可预览文件走兜底 (#6754)
This commit is contained in:
@@ -81,19 +81,29 @@ const SandboxEditor = ({ appId, chatId, outLinkAuthData }: Props) => {
|
||||
// 初始加载根目录的 loading 状态
|
||||
const [loadingRoot, setLoadingRoot] = useState(false);
|
||||
|
||||
// 读取文件内容 - 根据 language 来决定解码策略
|
||||
// 读取文件内容 - 根据 language 决定解码策略
|
||||
// - 媒体(image/audio/video)→ blob URL
|
||||
// - 其他 → 严格 UTF-8 解码;解不出来视为不可预览(如 xlsx/zip 等真二进制)
|
||||
const { runAsync: loadFile, loading: loadingFile } = useRequest(
|
||||
async (filePath: string, language: string): Promise<string> => {
|
||||
async (
|
||||
filePath: string,
|
||||
language: string
|
||||
): Promise<{ content: string; isUnknown: boolean }> => {
|
||||
const response = await getSandboxFile({ appId, chatId, outLinkAuthData, path: filePath });
|
||||
|
||||
const isBinary = getIsBinaryByLanguage(language);
|
||||
|
||||
if (isBinary) {
|
||||
const blob = await response.blob();
|
||||
return URL.createObjectURL(blob);
|
||||
} else {
|
||||
const content = await response.text();
|
||||
return content;
|
||||
return { content: URL.createObjectURL(blob), isUnknown: false };
|
||||
}
|
||||
|
||||
const buffer = await response.arrayBuffer();
|
||||
try {
|
||||
const content = new TextDecoder('utf-8', { fatal: true }).decode(buffer);
|
||||
return { content, isUnknown: false };
|
||||
} catch {
|
||||
return { content: '', isUnknown: true };
|
||||
}
|
||||
},
|
||||
{ manual: true }
|
||||
@@ -106,7 +116,7 @@ const SandboxEditor = ({ appId, chatId, outLinkAuthData }: Props) => {
|
||||
if (!targetPath) return;
|
||||
|
||||
const targetFile = openedFiles.find((f) => f.path === targetPath);
|
||||
if (!targetFile || targetFile.isBinary) return;
|
||||
if (!targetFile || targetFile.isBinary || targetFile.isUnknown) return;
|
||||
|
||||
await writeSandboxFile({
|
||||
appId,
|
||||
@@ -160,7 +170,7 @@ const SandboxEditor = ({ appId, chatId, outLinkAuthData }: Props) => {
|
||||
const language = getLanguageByFileName(fileName);
|
||||
const isBinary = getIsBinaryByLanguage(language);
|
||||
|
||||
const content = await loadFile(filePath, language);
|
||||
const { content, isUnknown } = await loadFile(filePath, language);
|
||||
|
||||
const newFile: OpenedFile = {
|
||||
path: filePath,
|
||||
@@ -168,7 +178,8 @@ const SandboxEditor = ({ appId, chatId, outLinkAuthData }: Props) => {
|
||||
content,
|
||||
language,
|
||||
isBinary,
|
||||
isDirty: false
|
||||
isDirty: false,
|
||||
isUnknown
|
||||
};
|
||||
|
||||
setOpenedFiles((prev) => [...prev, newFile]);
|
||||
@@ -214,7 +225,7 @@ const SandboxEditor = ({ appId, chatId, outLinkAuthData }: Props) => {
|
||||
// 当切换 tab 时,更新编辑器内容
|
||||
useEffect(() => {
|
||||
if (!editorRef.current || !activeFilePath || !activeFile) return;
|
||||
if (activeFile.isBinary) return;
|
||||
if (activeFile.isBinary || activeFile.isUnknown) return;
|
||||
|
||||
// 使用 ref 标记防止循环更新
|
||||
isUpdatingRef.current = true;
|
||||
|
||||
@@ -88,6 +88,11 @@ const EditorContent = ({
|
||||
const renderFileContent = () => {
|
||||
if (!activeFile) return null;
|
||||
|
||||
// 非媒体文件 UTF-8 解码失败 → 走兜底(如 xlsx/zip 等真二进制)
|
||||
if (activeFile.isUnknown) {
|
||||
return t('chat:sandbox_binary_file_no_preview');
|
||||
}
|
||||
|
||||
// 二进制文件预览 (图片/音频/视频)
|
||||
if (activeFile.isBinary) {
|
||||
const { language, content, name } = activeFile;
|
||||
|
||||
@@ -10,6 +10,8 @@ export type OpenedFile = {
|
||||
language: string;
|
||||
isBinary: boolean;
|
||||
isDirty: boolean;
|
||||
// 非媒体文件 UTF-8 解码失败时为 true,前端走「无法预览」兜底
|
||||
isUnknown?: boolean;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -80,7 +80,8 @@ const extensionToLang: Record<string, string[]> = {
|
||||
svg: ['svg'],
|
||||
pdf: ['pdf'],
|
||||
audio: ['mp3', 'wav', 'm4a', 'flac', 'ogg'],
|
||||
video: ['avi', 'mp4', 'webm', 'mov', 'm4v']
|
||||
// 仅保留浏览器 <video> 原生可解码的容器;avi/mkv/wmv/flv/mov/m4v 等走兜底
|
||||
video: ['mp4', 'webm']
|
||||
};
|
||||
|
||||
const langMap = Object.entries(extensionToLang).reduce(
|
||||
|
||||
Reference in New Issue
Block a user