diff --git a/src/backend/database/database.ts b/src/backend/database/database.ts
index b877de0f..5c61009d 100644
--- a/src/backend/database/database.ts
+++ b/src/backend/database/database.ts
@@ -46,7 +46,7 @@ const storage = multer.diskStorage({
const upload = multer({
storage: storage,
limits: {
- fileSize: 100 * 1024 * 1024, // 100MB limit
+ fileSize: 1024 * 1024 * 1024, // 1GB limit for database operations
},
fileFilter: (req, file, cb) => {
// Allow SQLite files
diff --git a/src/backend/ssh/file-manager.ts b/src/backend/ssh/file-manager.ts
index f96611a3..f9a5175b 100644
--- a/src/backend/ssh/file-manager.ts
+++ b/src/backend/ssh/file-manager.ts
@@ -58,9 +58,9 @@ app.use(
],
}),
);
-app.use(express.json({ limit: "100mb" }));
-app.use(express.urlencoded({ limit: "100mb", extended: true }));
-app.use(express.raw({ limit: "200mb", type: "application/octet-stream" }));
+app.use(express.json({ limit: "1gb" }));
+app.use(express.urlencoded({ limit: "1gb", extended: true }));
+app.use(express.raw({ limit: "5gb", type: "application/octet-stream" }));
interface SSHSession {
client: SSHClient;
@@ -492,8 +492,8 @@ app.get("/ssh/file_manager/ssh/readFile", (req, res) => {
sshConn.lastActive = Date.now();
- // First check file size to prevent loading huge files
- const MAX_READ_SIZE = 10 * 1024 * 1024; // 10MB - same as frontend limit
+ // Support large file reading - increased limit for better compatibility
+ const MAX_READ_SIZE = 500 * 1024 * 1024; // 500MB - much more reasonable limit
const escapedPath = filePath.replace(/'/g, "'\"'\"'");
// Get file size first
@@ -1641,8 +1641,8 @@ app.post("/ssh/file_manager/ssh/downloadFile", async (req, res) => {
.json({ error: "Cannot download directories or special files" });
}
- // Check file size (limit to 100MB for safety)
- const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
+ // Support large file downloads - increased limit for better compatibility
+ const MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024; // 5GB - reasonable for SSH file operations
if (stats.size > MAX_FILE_SIZE) {
fileLogger.warn("File too large for download", {
operation: "file_download",
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index 5c6387a0..4068b963 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -191,6 +191,7 @@
},
"common": {
"close": "Close",
+ "minimize": "Minimize",
"online": "Online",
"offline": "Offline",
"maintenance": "Maintenance",
@@ -661,7 +662,7 @@
"deleteItem": "Delete Item",
"currentPath": "Current Path",
"uploadFileTitle": "Upload File",
- "maxFileSize": "Max: 100MB (JSON) / 200MB (Binary)",
+ "maxFileSize": "Max: 1GB (JSON) / 5GB (Binary) - Large files supported",
"removeFile": "Remove File",
"clickToSelectFile": "Click to select a file",
"chooseFile": "Choose File",
@@ -819,7 +820,46 @@
"pinFile": "Pin file",
"addToShortcuts": "Add to shortcuts",
"selectLocationToSave": "Select location to save",
- "downloadToDefaultLocation": "Download to default location"
+ "downloadToDefaultLocation": "Download to default location",
+ "pasteFailed": "Paste failed",
+ "noUndoableActions": "No undoable actions",
+ "undoCopySuccess": "Undid copy operation: Deleted {{count}} copied files",
+ "undoCopyFailedDelete": "Undo failed: Could not delete any copied files",
+ "undoCopyFailedNoInfo": "Undo failed: Could not find copied file information",
+ "undoMoveSuccess": "Undid move operation: Moved {{count}} files back to original location",
+ "undoMoveFailedMove": "Undo failed: Could not move any files back",
+ "undoMoveFailedNoInfo": "Undo failed: Could not find moved file information",
+ "undoDeleteNotSupported": "Delete operation cannot be undone: Files have been permanently deleted from server",
+ "undoTypeNotSupported": "Unsupported undo operation type",
+ "undoOperationFailed": "Undo operation failed",
+ "unknownError": "Unknown error",
+ "enterPath": "Enter path...",
+ "editPath": "Edit path",
+ "confirm": "Confirm",
+ "cancel": "Cancel",
+ "folderName": "Folder name",
+ "find": "Find...",
+ "replaceWith": "Replace with...",
+ "startTyping": "Start typing...",
+ "fileSavedSuccessfully": "File saved successfully",
+ "autoSaveFailed": "Auto-save failed",
+ "fileAutoSaved": "File auto-saved",
+ "fileDownloadedSuccessfully": "File downloaded successfully",
+ "moveFileFailed": "Failed to move {{name}}",
+ "moveOperationFailed": "Move operation failed",
+ "canOnlyCompareFiles": "Can only compare two files",
+ "comparingFiles": "Comparing files: {{file1}} and {{file2}}",
+ "dragFailed": "Drag operation failed",
+ "filePinnedSuccessfully": "File \"{{name}}\" pinned successfully",
+ "pinFileFailed": "Failed to pin file",
+ "fileUnpinnedSuccessfully": "File \"{{name}}\" unpinned successfully",
+ "unpinFileFailed": "Failed to unpin file",
+ "shortcutAddedSuccessfully": "Folder shortcut \"{{name}}\" added successfully",
+ "addShortcutFailed": "Failed to add shortcut",
+ "operationCompletedSuccessfully": "{{operation}} {{count}} items successfully",
+ "operationCompleted": "{{operation}} {{count}} items",
+ "downloadFileSuccess": "File {{name}} downloaded successfully",
+ "downloadFileFailed": "Download failed"
},
"tunnels": {
"title": "SSH Tunnels",
diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json
index 5cf1dcad..b2860f90 100644
--- a/src/locales/zh/translation.json
+++ b/src/locales/zh/translation.json
@@ -190,6 +190,7 @@
},
"common": {
"close": "关闭",
+ "minimize": "最小化",
"online": "在线",
"offline": "离线",
"maintenance": "维护中",
@@ -676,7 +677,7 @@
"deleteItem": "删除项目",
"currentPath": "当前路径",
"uploadFileTitle": "上传文件",
- "maxFileSize": "最大:100MB(JSON)/ 200MB(二进制)",
+ "maxFileSize": "最大:1GB(JSON)/ 5GB(二进制)- 支持大文件",
"removeFile": "移除文件",
"clickToSelectFile": "点击选择文件",
"chooseFile": "选择文件",
@@ -826,7 +827,46 @@
"pinFile": "固定文件",
"addToShortcuts": "添加到快捷方式",
"selectLocationToSave": "选择位置保存",
- "downloadToDefaultLocation": "下载到默认位置"
+ "downloadToDefaultLocation": "下载到默认位置",
+ "pasteFailed": "粘贴失败",
+ "noUndoableActions": "没有可撤销的操作",
+ "undoCopySuccess": "已撤销复制操作:删除了 {{count}} 个复制的文件",
+ "undoCopyFailedDelete": "撤销失败:无法删除任何复制的文件",
+ "undoCopyFailedNoInfo": "撤销失败:找不到复制的文件信息",
+ "undoMoveSuccess": "已撤销移动操作:移回了 {{count}} 个文件到原位置",
+ "undoMoveFailedMove": "撤销失败:无法移回任何文件",
+ "undoMoveFailedNoInfo": "撤销失败:找不到移动的文件信息",
+ "undoDeleteNotSupported": "删除操作无法撤销:文件已从服务器永久删除",
+ "undoTypeNotSupported": "不支持撤销此类操作",
+ "undoOperationFailed": "撤销操作失败",
+ "unknownError": "未知错误",
+ "enterPath": "输入路径...",
+ "editPath": "编辑路径",
+ "confirm": "确认",
+ "cancel": "取消",
+ "folderName": "文件夹名",
+ "find": "查找...",
+ "replaceWith": "替换为...",
+ "startTyping": "开始输入...",
+ "fileSavedSuccessfully": "文件保存成功",
+ "autoSaveFailed": "自动保存失败",
+ "fileAutoSaved": "文件已自动保存",
+ "fileDownloadedSuccessfully": "文件下载成功",
+ "moveFileFailed": "移动 {{name}} 失败",
+ "moveOperationFailed": "移动操作失败",
+ "canOnlyCompareFiles": "只能对比两个文件",
+ "comparingFiles": "正在对比文件:{{file1}} 与 {{file2}}",
+ "dragFailed": "拖拽失败",
+ "filePinnedSuccessfully": "文件\"{{name}}\"已固定",
+ "pinFileFailed": "固定文件失败",
+ "fileUnpinnedSuccessfully": "文件\"{{name}}\"已取消固定",
+ "unpinFileFailed": "取消固定失败",
+ "shortcutAddedSuccessfully": "文件夹快捷方式\"{{name}}\"已添加",
+ "addShortcutFailed": "添加快捷方式失败",
+ "operationCompletedSuccessfully": "已{{operation}} {{count}} 个项目",
+ "operationCompleted": "已{{operation}} {{count}} 个项目",
+ "downloadFileSuccess": "文件 {{name}} 下载成功",
+ "downloadFileFailed": "下载失败"
},
"tunnels": {
"title": "SSH 隧道",
diff --git a/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx b/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx
index 8e9e1de8..06148b98 100644
--- a/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx
+++ b/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx
@@ -92,6 +92,7 @@ interface FileManagerGridProps {
onFileDiff?: (file1: FileItem, file2: FileItem) => void;
onSystemDragStart?: (files: FileItem[]) => void;
onSystemDragEnd?: (e: DragEvent) => void;
+ hasClipboard?: boolean;
// Linus式创建意图props
createIntent?: CreateIntent | null;
onConfirmCreate?: (name: string) => void;
@@ -194,6 +195,7 @@ export function FileManagerGrid({
onFileDiff,
onSystemDragStart,
onSystemDragEnd,
+ hasClipboard,
createIntent,
onConfirmCreate,
onCancelCreate,
@@ -894,7 +896,7 @@ export function FileManagerGrid({
break;
case "v":
case "V":
- if ((event.ctrlKey || event.metaKey) && onPaste) {
+ if ((event.ctrlKey || event.metaKey) && onPaste && hasClipboard) {
event.preventDefault();
onPaste();
}
@@ -1016,20 +1018,20 @@ export function FileManagerGrid({
}
}}
className="flex-1 px-2 py-1 bg-dark-hover border border-dark-border rounded text-sm focus:outline-none focus:ring-1 focus:ring-primary"
- placeholder="输入路径..."
+ placeholder={t("fileManager.enterPath")}
autoFocus
/>
) : (
@@ -1057,7 +1059,7 @@ export function FileManagerGrid({
@@ -1473,7 +1475,7 @@ function CreateIntentGridItem({
onKeyDown={handleKeyDown}
onBlur={() => onConfirm?.(inputName.trim())}
className="w-full max-w-[120px] rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1 text-xs text-center text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[2px] outline-none"
- placeholder={intent.type === 'directory' ? 'Folder name' : 'File name'}
+ placeholder={intent.type === 'directory' ? t('fileManager.folderName') : t('fileManager.fileName')}
/>
diff --git a/src/ui/Desktop/Apps/File Manager/FileManagerModern.tsx b/src/ui/Desktop/Apps/File Manager/FileManagerModern.tsx
index 587f110d..9266aca8 100644
--- a/src/ui/Desktop/Apps/File Manager/FileManagerModern.tsx
+++ b/src/ui/Desktop/Apps/File Manager/FileManagerModern.tsx
@@ -130,7 +130,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
const { isDragging, dragHandlers } = useDragAndDrop({
onFilesDropped: handleFilesDropped,
onError: (error) => toast.error(error),
- maxFileSize: 100, // 100MB
+ maxFileSize: 5120, // 5GB - support large files like SSH tools should
});
// 拖拽到桌面功能
@@ -792,13 +792,13 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
if (hasRenamed) {
toast.success(
- `已${operationText} ${successCount} 个项目,部分文件已自动重命名避免冲突`,
+ t("fileManager.operationCompletedSuccessfully", { operation: operationText, count: successCount }),
);
} else {
- toast.success(`已${operationText} ${successCount} 个项目`);
+ toast.success(t("fileManager.operationCompleted", { operation: operationText, count: successCount }));
}
} else {
- toast.success(`已${operationText} ${successCount} 个项目`);
+ toast.success(t("fileManager.operationCompleted", { operation: operationText, count: successCount }));
}
}
@@ -811,13 +811,13 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
setClipboard(null);
}
} catch (error: any) {
- toast.error(`粘贴失败: ${error.message || "Unknown error"}`);
+ toast.error(`${t("fileManager.pasteFailed")}: ${error.message || t("fileManager.unknownError")}`);
}
}
async function handleUndo() {
if (undoHistory.length === 0) {
- toast.info("没有可撤销的操作");
+ toast.info(t("fileManager.noUndoableActions"));
return;
}
@@ -860,14 +860,14 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
// 移除最后一个撤销记录
setUndoHistory((prev) => prev.slice(0, -1));
toast.success(
- `已撤销复制操作:删除了 ${successCount} 个复制的文件`,
+ t("fileManager.undoCopySuccess", { count: successCount }),
);
} else {
- toast.error("撤销失败:无法删除任何复制的文件");
+ toast.error(t("fileManager.undoCopyFailedDelete"));
return;
}
} else {
- toast.error("撤销失败:找不到复制的文件信息");
+ toast.error(t("fileManager.undoCopyFailedNoInfo"));
return;
}
break;
@@ -902,34 +902,34 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
// 移除最后一个撤销记录
setUndoHistory((prev) => prev.slice(0, -1));
toast.success(
- `已撤销移动操作:移回了 ${successCount} 个文件到原位置`,
+ t("fileManager.undoMoveSuccess", { count: successCount }),
);
} else {
- toast.error("撤销失败:无法移回任何文件");
+ toast.error(t("fileManager.undoMoveFailedMove"));
return;
}
} else {
- toast.error("撤销失败:找不到移动的文件信息");
+ toast.error(t("fileManager.undoMoveFailedNoInfo"));
return;
}
break;
case "delete":
// 删除操作无法真正撤销(文件已从服务器删除)
- toast.info("删除操作无法撤销:文件已从服务器永久删除");
+ toast.info(t("fileManager.undoDeleteNotSupported"));
// 仍然移除历史记录,因为用户已经知道了这个限制
setUndoHistory((prev) => prev.slice(0, -1));
return;
default:
- toast.error("不支持撤销此类操作");
+ toast.error(t("fileManager.undoTypeNotSupported"));
return;
}
// 刷新文件列表
handleRefreshDirectory();
} catch (error: any) {
- toast.error(`撤销操作失败: ${error.message || "Unknown error"}`);
+ toast.error(`${t("fileManager.undoOperationFailed")}: ${error.message || t("fileManager.unknownError")}`);
console.error("Undo failed:", error);
}
}
@@ -1117,7 +1117,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
}
} catch (error: any) {
console.error(`Failed to move file ${file.name}:`, error);
- toast.error(`移动 ${file.name} 失败: ${error.message}`);
+ toast.error(t("fileManager.moveFileFailed", { name: file.name }) + ": " + error.message);
}
}
@@ -1156,14 +1156,14 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
}
} catch (error: any) {
console.error("Drag move operation failed:", error);
- toast.error(`移动操作失败: ${error.message}`);
+ toast.error(t("fileManager.moveOperationFailed") + ": " + error.message);
}
}
// 拖拽处理:文件拖到文件 = diff对比操作
function handleFileDiff(file1: FileItem, file2: FileItem) {
if (file1.type !== "file" || file2.type !== "file") {
- toast.error("只能对比两个文件");
+ toast.error(t("fileManager.canOnlyCompareFiles"));
return;
}
@@ -1202,7 +1202,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
zIndex: Date.now(),
});
- toast.success(`正在对比文件: ${file1.name} 与 ${file2.name}`);
+ toast.success(t("fileManager.comparingFiles", { file1: file1.name, file2: file2.name }));
}
// 拖拽到桌面处理函数
@@ -1234,7 +1234,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
}
} catch (error: any) {
console.error("拖拽到桌面失败:", error);
- toast.error(`拖拽失败: ${error.message || "未知错误"}`);
+ toast.error(t("fileManager.dragFailed") + ": " + (error.message || t("fileManager.unknownError")));
}
}
@@ -1344,10 +1344,10 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
await addPinnedFile(currentHost.id, file.path, file.name);
setPinnedFiles((prev) => new Set([...prev, file.path]));
setSidebarRefreshTrigger((prev) => prev + 1); // 触发侧边栏刷新
- toast.success(`文件"${file.name}"已固定`);
+ toast.success(t("fileManager.filePinnedSuccessfully", { name: file.name }));
} catch (error) {
console.error("Failed to pin file:", error);
- toast.error("固定文件失败");
+ toast.error(t("fileManager.pinFileFailed"));
}
}
@@ -1363,10 +1363,10 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
return newSet;
});
setSidebarRefreshTrigger((prev) => prev + 1); // 触发侧边栏刷新
- toast.success(`文件"${file.name}"已取消固定`);
+ toast.success(t("fileManager.fileUnpinnedSuccessfully", { name: file.name }));
} catch (error) {
console.error("Failed to unpin file:", error);
- toast.error("取消固定失败");
+ toast.error(t("fileManager.unpinFileFailed"));
}
}
@@ -1378,10 +1378,10 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
const folderName = path.split("/").pop() || path;
await addFolderShortcut(currentHost.id, path, folderName);
setSidebarRefreshTrigger((prev) => prev + 1); // 触发侧边栏刷新
- toast.success(`文件夹快捷方式"${folderName}"已添加`);
+ toast.success(t("fileManager.shortcutAddedSuccessfully", { name: folderName }));
} catch (error) {
console.error("Failed to add shortcut:", error);
- toast.error("添加快捷方式失败");
+ toast.error(t("fileManager.addShortcutFailed"));
}
}
@@ -1613,6 +1613,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
onCut={handleCutFiles}
onPaste={handlePasteFiles}
onUndo={handleUndo}
+ hasClipboard={!!clipboard}
onFileDrop={handleFileDrop}
onFileDiff={handleFileDiff}
onSystemDragStart={handleFileDragStart}
diff --git a/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx b/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx
index 800ea87b..40484cb8 100644
--- a/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx
+++ b/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx
@@ -139,11 +139,11 @@ export function DiffViewer({
document.body.removeChild(link);
URL.revokeObjectURL(url);
- toast.success(`文件下载成功: ${file.name}`);
+ toast.success(t("fileManager.downloadFileSuccess", { name: file.name }));
}
} catch (error: any) {
console.error("Failed to download file:", error);
- toast.error(`下载失败: ${error.message || "未知错误"}`);
+ toast.error(t("fileManager.downloadFileFailed") + ": " + (error.message || t("fileManager.unknownError")));
}
};
diff --git a/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx b/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx
index 4ad2bc24..89e42f02 100644
--- a/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx
+++ b/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx
@@ -221,7 +221,7 @@ export function DraggableWindow({
e.stopPropagation();
onMinimize();
}}
- title="最小化"
+ title={t("common.minimize")}
>