Fix file upload 400 Bad Request error in file manager

- Correct uploadSSHFile parameter order and types in FileManagerModern.tsx:
  * Pass directory path instead of full file path
  * Extract file.name instead of passing File object
  * Read file content using FileReader API
  * Support both text and binary files with proper encoding

- Apply same fixes to FileManagerOperations.tsx upload functionality

- Add intelligent file type detection:
  * Text files read as UTF-8 strings
  * Binary files read as ArrayBuffer and converted to base64
  * Support common text file extensions and MIME types

- Include hostId parameter in uploadSSHFile calls for proper authentication

This resolves the "File path, name, and content are required" error
by ensuring all required parameters are correctly provided to the API.
This commit is contained in:
ZacharyZcR
2025-09-17 11:11:35 +08:00
parent 8fd46f2383
commit 5ec9451ef2
2 changed files with 85 additions and 5 deletions

View File

@@ -298,11 +298,53 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
// 确保SSH连接有效
await ensureSSHConnection();
const targetPath = currentPath.endsWith('/')
? `${currentPath}${file.name}`
: `${currentPath}/${file.name}`;
// 读取文件内容
const fileContent = await new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onerror = () => reject(reader.error);
await uploadSSHFile(sshSessionId, targetPath, file);
// 检查文件类型,决定读取方式
const isTextFile = file.type.startsWith('text/') ||
file.type === 'application/json' ||
file.type === 'application/javascript' ||
file.type === 'application/xml' ||
file.name.match(/\.(txt|json|js|ts|jsx|tsx|css|html|htm|xml|yaml|yml|md|py|java|c|cpp|h|sh|bat|ps1)$/i);
if (isTextFile) {
reader.onload = () => {
if (reader.result) {
resolve(reader.result as string);
} else {
reject(new Error('Failed to read text file content'));
}
};
reader.readAsText(file);
} else {
reader.onload = () => {
if (reader.result instanceof ArrayBuffer) {
const bytes = new Uint8Array(reader.result);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
const base64 = btoa(binary);
resolve(base64);
} else {
reject(new Error('Failed to read binary file'));
}
};
reader.readAsArrayBuffer(file);
}
});
await uploadSSHFile(
sshSessionId,
currentPath,
file.name,
fileContent,
currentHost?.id,
undefined // userId - will be handled by backend
);
toast.success(t("fileManager.fileUploadedSuccessfully", { name: file.name }));
loadDirectory(currentPath);
} catch (error: any) {

View File

@@ -80,7 +80,45 @@ export function FileManagerOperations({
);
try {
const content = await uploadFile.text();
// 读取文件内容 - 支持文本和二进制文件
const content = await new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onerror = () => reject(reader.error);
// 检查文件类型,决定读取方式
const isTextFile = uploadFile.type.startsWith('text/') ||
uploadFile.type === 'application/json' ||
uploadFile.type === 'application/javascript' ||
uploadFile.type === 'application/xml' ||
uploadFile.name.match(/\.(txt|json|js|ts|jsx|tsx|css|html|htm|xml|yaml|yml|md|py|java|c|cpp|h|sh|bat|ps1)$/i);
if (isTextFile) {
reader.onload = () => {
if (reader.result) {
resolve(reader.result as string);
} else {
reject(new Error('Failed to read text file content'));
}
};
reader.readAsText(uploadFile);
} else {
reader.onload = () => {
if (reader.result instanceof ArrayBuffer) {
const bytes = new Uint8Array(reader.result);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
const base64 = btoa(binary);
resolve(base64);
} else {
reject(new Error('Failed to read binary file'));
}
};
reader.readAsArrayBuffer(uploadFile);
}
});
const { uploadSSHFile } = await import("@/ui/main-axios.ts");
const response = await uploadSSHFile(