我使用Indy IDFTP制作目录。我需要找到一种可靠的方法来确定目录是否存在以及它是否存在,以便调用MakeDir。我尝试了以下代码,但是在调用List时没有发生异常,因此即使当时目录不存在,MakeDir也没有执行。如何确定目录是否存在并创建目录(如果该目录不存在)?
{ Check to see if the '/public_html/XXX/' + iDomain + 'Thumbnails' directory exists }
try
IdFTP1.List(nil, '/public_html/XXX/' + iDomain + 'Thumbnails', False);
except
on e: EIdReplyRFCError do
begin
{ '/public_html/XXX/' + iDomain + 'Thumbnails' directory does not exist }
StatusBar1.SimpleText := 'Making thumbnail directory...';
StatusBar1.Update;
iFolder := '/public_html/XXX/' + iDomain;
{ Change directory to /public_html/XXX/iDomain }
IdFTP1.ChangeDir(iFolder);
iFolder := 'Thumbnails';
{ Create FTP Directory for Thumbnails }
IdFTP1.MakeDir(iFolder);
end;
end;
在我测试期间,目录不存在,但在运行时e是零?我的方法是否正确?
答案 0 :(得分:7)
如果TIdFTP.List()
没有引发异常,则FTP服务器很可能会返回450
回复代码,这意味着"未采取请求的文件操作"。 TIdFTP.InternalGet()
(由TIdFTP.List()
,TIdFTP.ExtListDir()
和TIdFTP.Get()
使用)不会将450
视为错误情况,因为某些服务器(如Ericsson Switch FTP) )列出空的但存在的目录的内容时发送450
,因此没有要发送的列表数据。但是,当请求的目录不存在时,某些服务器会发送450
。 TIdFTP.List()
不会尝试区分。但是,如果TIdFTP.List()
未引发异常,您可以查看TIdFTP.LastCmdResult
属性,以便在需要时手动区分。
此外,您不能仅仅依赖于引发异常以表示该文件夹不存在的事实。可能发生任何数量的可能错误。您必须实际查看错误并采取相应措施,例如:
var
Exists: Boolean;
try
IdFTP1.List(nil, '/public_html/XXX/' + iDomain + 'Thumbnails', False);
Exists := True;
if IdFTP1.LastCmdResult.NumericCode = 450 then
begin
if (IdFTP1.LastCmdResult.Text.Text has a message like 'No such file or directory' or similar) then begin
Exists := False;
end;
// look for other possible text messages...
end;
except
on e: EIdReplyRFCError do
begin
if (e.ErrorCode <> 550) or (e.Message does not have a message like 'Directory not found' or similar) then begin
raise;
end;
Exists := false;
end;
end;
if not Exists then
begin
{ '/public_html/XXX/' + iDomain + 'Thumbnails' directory does not exist }
StatusBar1.SimpleText := 'Making thumbnail directory...';
StatusBar1.Update;
iFolder := '/public_html/XXX/' + iDomain;
{ Change directory to /public_html/XXX/iDomain }
IdFTP1.ChangeDir(iFolder);
iFolder := 'Thumbnails';
{ Create FTP Directory for Thumbnails }
IdFTP1.MakeDir(iFolder);
end;
更好的方法是:
ChangeDir()
直接到目标目录并查看它是否失败。如果是这样,开始向后走过路径,为每个父目录调用ChangeDir()
,直到最终成功,然后使用MakeDir()
和ChangeDir()
向上走回路径以创建缺少的子目录根据需要。
从路径中的第一个目录开始,然后ChangeDir()
开始,然后List()
查看下一个子文件夹是否存在,MakeDir()
如果需要,然后ChangeDir()
到它,并根据需要重复,直到到达目标目录。
欢迎使用FTP。它不是一个非常有效的目录管理协议。
答案 1 :(得分:0)
以下是上传文件夹的方法。 Source
{
Upload the LocalDir to an FTP server, in the RemoteDir.
If RemoteDir does not exist it is created.
All files and subfolders of LocalDir will be uploaded.
FTP parameters (username, password, server) must be already provided.
The caller must connnect to the server before calling UploadFolderToFtp and disconnect after that }
procedure UploadFolderToFtp(FTP: TIdFTP; LocalDir, RemoteDir, Filter: string);
procedure GoToSubDir(SubDir: string);
VAR
details, nodetails: TStringList;
k: Integer;
begin
details := TStringList.Create; //get folder contents from ftp. one with details, one without
nodetails := TStringList.Create;
TRY
FTP.List(details, '', True);
FTP.List(nodetails, '', False);
//we only want to have directories in the list (without '.' and '..')
for k := details.Count - 1 downto 0 do
if details.Strings[k] <> '' then
if (PosInsensitive('dir', details.Strings[k]) < 1)
OR (nodetails.Strings[k] = '.')
OR (nodetails.Strings[k] = '..') then
begin
details.Delete(k);
nodetails.Delete(k);
end;
//if our directory does not exists on the server, create it
if nodetails.IndexOf(SubDir) = -1
then FTP.MakeDir(SubDir);
FINALLY
FreeAndNil(Details);
FreeAndNil(nodetails);
END;
FTP.ChangeDir(SubDir); //change into next directory on server
end;
procedure uploadDir(dir: string);
VAR
s: string;
List: TStringList;
begin
List:= ListDirectoriesOf(dir, FALSE, FALSE); //iterate through subdirectories
for s in List DO
begin
GoToSubDir(s);
uploadDir(dir + s + '\'); //and also locally go into the next subfolder
FTP.ChangeDirUp; //we have to go one directory up after leaving the recursion
end;
FreeAndNil(List);
List:= ListFilesOf(dir, Filter, FALSE, FALSE); //iterate through files
for s in List DO
begin
Assert(s > '', 'File name should not be empty!');
FTP.Put(dir + s, s); //if it's only a file, upload it to the current directory;
end;
FreeAndNil(List);
end;
VAR
subdir, dir: string;
begin
//does not matter if RemoteDir is like 'dir\dir' or 'dir/dir'
dir := StringReplace(RemoteDir, '\', '/', [rfReplaceAll]);
if dir <> '' then
begin
if dir[1] = '/' then Delete(dir, 1, 1); //remove first '/' if there's one
if dir[Length(dir)] <> '/' then dir := dir + '/'; // add a '/' at the end
//loop through our remote-directories
WHILE Pos('/', dir) > 0 DO
begin
SubDir:= system.Copy(dir, 1, Pos('/', dir) - 1);
//if our directory does not exists on the server, we create it
GoToSubDir(SubDir);
//remove first directory from path ('your/directory/subdir/' --> 'directory/subdir/')
Delete(dir, 1, Pos('/', dir));
end;
end;
dir := LocalDir;
if dir[Length(dir)] <> '\'
then dir := dir + '\';
uploadDir(dir); // begin the upload
end;
procedure TfrmFTP.Button1Click(Sender: TObject);
begin
if Connect {Set parameters for FTP and connect to server }
then UploadFolderToFtp(ftp, 'c:\test\', RemoteDir, '*.*')
else SwMessage('Cannot connect to '+ FTP.ServerHOST);
Disconnect;
end;
-
ListDirectoriesOf&amp; ListFilesOf是一个返回指定文件夹的子目录/文件的函数(它返回非完整路径)
答案 2 :(得分:0)
简单的解决方案是
IdFTP.ChangeDir('/www/image/catalog/'); // connect to to directory where you want to add folder
try
IdFTP.MakeDir(new_Dir_name); // try to create folder
IdFTP.ChangeDir('/www/image/catalog/' + new_Dir_name ); // connect to new folder
except
IdFTP.ChangeDir('/www/image/catalog/' + new_Dir_name ); // if folder exist just connect to folder which exist
end;