feat: add web UI file upload to Docker containers

This commit is contained in:
HarikrishnanD
2025-11-05 11:55:40 +05:30
parent 1ce153371a
commit c5eb31ab90
5 changed files with 335 additions and 1 deletions

View File

@@ -1,3 +1,6 @@
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
execAsync,
execAsyncRemote,
@@ -472,3 +475,85 @@ export const getApplicationInfo = async (
return appArray;
} catch {}
};
export const uploadFileToContainer = async (
containerId: string,
fileBuffer: Buffer,
fileName: string,
destinationPath: string,
serverId?: string | null,
): Promise<void> => {
const containerIdRegex = /^[a-zA-Z0-9.\-_]+$/;
if (!containerIdRegex.test(containerId)) {
throw new Error("Invalid container ID");
}
// Ensure destination path starts with /
const normalizedPath = destinationPath.startsWith("/")
? destinationPath
: `/${destinationPath}`;
if (serverId) {
// Remote server: transfer file via base64 encoding using heredoc
const base64Content = fileBuffer.toString("base64");
const tempFileName = `dokploy-upload-${Date.now()}-${fileName.replace(/[^a-zA-Z0-9.-]/g, "_")}`;
const tempPath = `/tmp/${tempFileName}`;
try {
// Create temp directory and write file on remote server using heredoc
// This handles large files and special characters better than echo
const writeCommand = `cat << 'EOF' | base64 -d > "${tempPath}"
${base64Content}
EOF
`;
await execAsyncRemote(serverId, writeCommand);
// Copy file into container
const copyCommand = `docker cp "${tempPath}" "${containerId}:${normalizedPath}"`;
await execAsyncRemote(serverId, copyCommand);
// Clean up temp file
const cleanupCommand = `rm -f "${tempPath}"`;
await execAsyncRemote(serverId, cleanupCommand);
} catch (error) {
// Try to clean up on error
try {
await execAsyncRemote(serverId, `rm -f "${tempPath}"`);
} catch {
// Ignore cleanup errors
}
throw new Error(
`Failed to upload file to container: ${error instanceof Error ? error.message : String(error)}`,
);
}
} else {
// Local server: use temp directory
const tempDir = await mkdtemp(join(tmpdir(), "dokploy-upload-"));
const tempFilePath = join(tempDir, fileName);
try {
// Write file to temp directory
await writeFile(tempFilePath, fileBuffer);
// Copy file into container
const copyCommand = `docker cp "${tempFilePath}" "${containerId}:${normalizedPath}"`;
await execAsync(copyCommand);
// Clean up temp directory
await rm(tempFilePath, { force: true });
await rm(tempDir, { recursive: true, force: true });
} catch (error) {
// Try to clean up on error
try {
await rm(tempFilePath, { force: true });
await rm(tempDir, { recursive: true, force: true });
} catch {
// Ignore cleanup errors
}
throw new Error(
`Failed to upload file to container: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
};