Create FTP Server

hi, how would I go about creating a FTP Server, using the idFTPServer1 from indy.

has to be able to list the selected directory, and move/delete/edit, upload/download.

if you have any code snipets and links please post them below.

I will give more points when posting working code than to post links, posting links with code will give u both.
LVL 2
SaLzAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DeerBearCommented:
Hi,

I'm having problems in providing source, because Indy FTP server gives me a
problem. Will get back asap when I'll be understanding what goes wrong.

Cheers,

Andrew
0
SaLzAuthor Commented:
jonas78, the links you provided are far from a ftp server, the 1+4 links are for clients and use NMFTP1, 2+3 have no useful information about creating a ftp server, but its a start, do you know any other links or know of components for ftp other than indy and the links associated with them.

with indy ftp server, I can connect to the ftp server, but when the client ask for the listing directory, am stumped.

the ftp server isn't well documented, and having trouble finding information on the means of creating a ftp server.

any code/links about 'ftp server' would be much appreciated.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

DeerBearCommented:
Ok, this code should get you started.

Please consider that there're bugs, so you'll need to fix it, since I wrote it "flying" few minutes ago.
But should be nuff for a kickstart.

Enjoy!!!!

unit MainCode;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, DBClient, StdCtrls, IdBaseComponent, IdComponent,
  IdTCPServer, IdFTPServer, idFTPList;

type
  TMainFrm = class(TForm)
    GroupBox1: TGroupBox;
    FolderRootEdit: TEdit;
    StartBtn: TButton;
    StopBtn: TButton;
    FTPSrv: TIdFTPServer;
    GroupBox2: TGroupBox;
    LogMemo: TMemo;
    procedure StartBtnClick(Sender: TObject);
    procedure StopBtnClick(Sender: TObject);
    procedure FTPSrvListDirectory(ASender: TIdFTPServerThread;
      const APath: String; ADirectoryListing: TIdFTPListItems);
    procedure FTPSrvGetFileSize(ASender: TIdFTPServerThread;
      const AFilename: String; var VFileSize: Int64);
    procedure FTPSrvConnect(AThread: TIdPeerThread);
    procedure FTPSrvStoreFile(ASender: TIdFTPServerThread;
      const AFileName: String; AAppend: Boolean; var VStream: TStream);
    procedure FTPSrvRetrieveFile(ASender: TIdFTPServerThread;
      const AFileName: String; var VStream: TStream);
    procedure FTPSrvDeleteFile(ASender: TIdFTPServerThread;
      const APathName: String);
  private
    function GetBaseDir: String;
    { Private declarations }
  public
    { Public declarations }
    property BaseDir : String read GetBaseDir;
  end;

var
  MainFrm: TMainFrm;

implementation

{$R *.dfm}

function TMainFrm.GetBaseDir: String;
begin
  if FolderRootEdit.Text = '' then
  begin
    Result := ExtractFilePath( ParamStr( 0 ) )+'pub';
  end;
end;

procedure TMainFrm.StartBtnClick(Sender: TObject);
begin
  FTPSrv.Active := True;
  ChDir( BaseDir );
end;

procedure TMainFrm.StopBtnClick(Sender: TObject);
begin
  FTPSrv.Active := False;
end;

procedure TMainFrm.FTPSrvListDirectory(ASender: TIdFTPServerThread;
  const APath: String; ADirectoryListing: TIdFTPListItems);
var SR : TSearchRec;
    FTPLI : TidFTPListItem;
begin
//  GetFolderList( APath, FileNames );
(*  ADirectoryListing.LoadList( FileNames );
  ADirectoryListing.ListFormat := flfDos;*)
  if FindFirst( '*.*',faAnyFile,SR ) = 0 then
  begin
    FTPLI := ADirectoryListing.Add;
    FTPLI.FileName := SR.Name;
    FTPLI.Size := SR.Size;
    if( SR.Attr and faDirectory ) = faDirectory then
      FTPLI.ItemType := ditDirectory
    else
      FTPLI.ItemType := ditFile;
    while FindNext( SR ) = 0 do
    begin
      FTPLI := ADirectoryListing.Add;
      FTPLI.FileName := SR.Name;
      FTPLI.Size := SR.Size;
      if( SR.Attr and faDirectory ) = faDirectory then
        FTPLI.ItemType := ditDirectory
      else
        FTPLI.ItemType := ditFile;
    end;
    FindClose( SR );
  end;
end;

procedure TMainFrm.FTPSrvGetFileSize(ASender: TIdFTPServerThread;
  const AFilename: String; var VFileSize: Int64);
var F : File;
begin
  AssignFile( F,AFileName );
  Reset( F );
  VFileSize := FileSize( F );
  CloseFile( F );
end;

procedure TMainFrm.FTPSrvConnect(AThread: TIdPeerThread);
begin
  LogMemo.Lines.Add( 'Connection from '+AThread.Connection.Socket.LocalName );
end;

procedure TMainFrm.FTPSrvStoreFile(ASender: TIdFTPServerThread;
  const AFileName: String; AAppend: Boolean; var VStream: TStream);
var FStream : TFileStream;
    CreateMode : Word;
begin
  if AAppend then
    CreateMode := fmOpenReadWrite
  else
    CreateMode := fmCreate;
  FStream := TFileStream.Create( AFileName,CreateMode );
  if AAppend then
    FStream.Position := FStream.Size;
  FStream.CopyFrom( VStream, VStream.Size );
end;

procedure TMainFrm.FTPSrvRetrieveFile(ASender: TIdFTPServerThread;
  const AFileName: String; var VStream: TStream);
begin
  VStream := TMemoryStream.Create;
  VStream.LoadFromFile( AFileName );
end;

procedure TMainFrm.FTPSrvDeleteFile(ASender: TIdFTPServerThread;
  const APathName: String);
begin
  DeleteFile( APathName );
end;

end.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SaLzAuthor Commented:
ok, we have got the listing.

procedure TForm1.FTPSrvListDirectory(ASender: TIdFTPServerThread;
  const APath: String; ADirectoryListing: TIdFTPListItems);
var
    item: TIdFTPListItem;
begin
  item := ADirectoryListing.Add;
  item.FileName := 'Hello.text';
  item.Size:=100000;
end;

how do we move from folder to folder? and display what location we are at?

if we have C:\pub\ as our location, if we navigate all the way though the subfolders to C:\pub\1\2\3\ how do we get the location?
0
DeerBearCommented:
That's *really* the case that you give a closer look to my code :-)

Cheers,

Andrew
0
SaLzAuthor Commented:
I've already taken a closer look at the code and nope.

it gives errors here saying LoadFromFile, undecared identifier. u missed anything out in uses? or types?

procedure TForm1.FTPSrvRetrieveFile(ASender: TIdFTPServerThread;
  const AFileName: String; var VStream: TStream);
begin
  VStream := TMemoryStream.Create;
  VStream.LoadFromFile( AFileName );
end;
=========

and on ListDirectory u missed the directory path, its just got '*.*'  so put in 'C:\' sure it lists, but I can't go anywhere else from that directory.

procedure TForm1.FTPSrvListDirectory(ASender: TIdFTPServerThread;
  const APath: String; ADirectoryListing: TIdFTPListItems);
var SR : TSearchRec;
    FTPLI : TidFTPListItem;
begin
//  GetFolderList( APath, FileNames );
(*  ADirectoryListing.LoadList( FileNames );
  ADirectoryListing.ListFormat := flfDos;*)
  if FindFirst( '*.*',faAnyFile,SR ) = 0 then
  begin
    FTPLI := ADirectoryListing.Add;
    FTPLI.FileName := SR.Name;
    FTPLI.Size := SR.Size;
    if( SR.Attr and faDirectory ) = faDirectory then
      FTPLI.ItemType := ditDirectory
    else
      FTPLI.ItemType := ditFile;
    while FindNext( SR ) = 0 do
    begin
      FTPLI := ADirectoryListing.Add;
      FTPLI.FileName := SR.Name;
      FTPLI.Size := SR.Size;
      if( SR.Attr and faDirectory ) = faDirectory then
        FTPLI.ItemType := ditDirectory
      else
        FTPLI.ItemType := ditFile;
    end;
    FindClose( SR );
  end;
end;
0
DeerBearCommented:
Hi,

You might want to use ChDir API to actually change folder.
But remember you're talking multiple clients here, so you would be best in keeping track of each folder in a
separate data object.

Look at TIdPeerThread for more informations.

Cheers,

Andrew
0
TiborKiCommented:
You don't need to use Indy, becaouse it sucks!
Much better is if you use ICS!


http://www.overbyte.be/arch/icsbeta20050109.zip

Samples are inside, with full source code!

PS: If you solve problem by using ICS, please accept me!

Tibor
0
DeerBearCommented:
The main advantage about Indy is that it's shipping with Delphi, thus can be found in any newer version of Delphi.
This might result in a good advantage over ICS, which is also a bit more complex to master than Indy.

Cheers,

Andrew
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.