We are trying to move a file to an FTP site. We need to create a folder structure like this:
/deeply/nested/folder/structure/index.html
Yesterday, we realized we can't create more than one folder at a time, so this doesn't work:
MKD /deeply/nested/folder/structure
So, in code, we wrote a loop that created each folder, one at a time, ignoring errors caused by the folder already existing. Ignoring errors is gross.
Is a way to create these nested folders in one action, rather than multiple? Is there a command to see if a folder already exists? If we just push the file out including the full path, will FTP be smart enough to create the directories for me?
No, there's no standard way to create a folder with subfolders. There's also no standard way to check if directory exists. You would need to use LIST or MLSD (where supported) and parse the result for this. Can't you just use some third-party component that supports the needed functionality?
I wrote a simple C# example here, maybe someone will need this code.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
namespace Deployer
{
public class RecursiveFolderUploader
{
private const string SrcFullPath = @"C:\prg\Snowinmars\Snowinmars.Ui";
private readonly IList<string> foldersOnServer;
private Client ftpClient; // that's your ftp client, init it
public RecursiveFolderUploader()
{
this.foldersOnServer = new List<string>();
}
private void UploadAll(DirectoryInfo directoryInfo)
{
// ftp://login:[email protected]/path/to/root/mydir/anotherdir/file.dat
// ^________________uri_______________________^_relevationPath_^
foreach (var file in directoryInfo.EnumerateFiles())
{
if (!file.Directory.FullName.StartsWith(RecursiveFolderUploader.SrcFullPath))
{
throw new InvalidOperationException($"File {file.FullName} is not from {RecursiveFolderUploader.SrcFullPath} folder");
}
string relevationPath; // all folders from root up to file
if (file.Directory.FullName.Length == RecursiveFolderUploader.SrcFullPath.Length)
{
relevationPath = "";
}
else
{
relevationPath = file.Directory.FullName.Substring(RecursiveFolderUploader.SrcFullPath.Length, file.Directory.FullName.Length - RecursiveFolderUploader.SrcFullPath.Length);
if (relevationPath.StartsWith("\\"))
{
relevationPath = relevationPath.Remove(0, 1);
}
}
string destination;
if (string.IsNullOrWhiteSpace(relevationPath))
{
destination = file.Name;
}
else
{
destination = Path.Combine(relevationPath, file.Name).Replace("\\", "/");
}
try
{
ftpClient.UploadFile(file.FullName, destination);
}
catch (WebException e)
{
// that means that there's no such folder or something else goes wrong
// we can check it by creating folders and try again
var parts = relevationPath.Replace("\\", "/").Split('/');
for (int i = 1; i <= parts.Length; i++)
{
var path = string.Join("/", parts.Take(i));
if (!foldersOnServer.Contains(path))
{
ftpClient.MakeDirectory(path);
foldersOnServer.Add(path);
}
}
try
{
ftpClient.UploadFile(file.FullName, destination);
}
catch (Exception innerE)
{
// if it doesn't help - trouble isn't in folders
throw new WebException($"Can't find folder {relevationPath}", innerE);
}
}
}
foreach (var directory in directoryInfo.EnumerateDirectories())
{
UploadAll(directory);
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With