05 junio 2007

Subiendo archivos por FTP con INDY

Para subir archivos por FTP utilizaremos el objeto TIdFTP de la paleta de componentes Indy Clients. Para poder utilizar dicho objeto debemos añadirlo en la seccion interface:

uses
Windows, Messages, ......, IdFTP, IdComponent;

La unidad IdComponent la utilizaremos luego para controlar eventos del componente FTP. El objeto lo creamos en tiempo de ejecución:

procedure SubirArchivo( sArchivo: String );
var
FTP: TIdFTP;
begin
FTP := TIdFTP.Create( nil );

Antes de subir un archivo hay que conectar con el servidor dando usuario y password:

FTP.Username := 'usuario';
FTP.Password := 'miclave';
FTP.Host := 'miftp.midominio.com';

try
FTP.Connect;
except
raise Exception.Create( 'No se ha podido conectar con el servidor ' + FTP.Host );
end;

Ahora ya estamos listos para enviar el archivo, pero antes debemos ir al directorio del servidor donde deseamos subir el archivo:

FTP.ChangeDir( '/misarchivos/copiaseguridad/' );

Para subir un archivo tenemos el método Put, el cual toma como primer parámetro la ruta y nombre del archivo a subir, como segundo parámetro el nombre que va a tener el archivo en el servidor (se supone que el mismo) y como tercer parámetro si deseamos añadir a un archivo ya existente o crear el archivo de nuevo:

FTP.Put( sArchivo, ExtractFileName( sArchivo ), False );

En nuestro caso hemos subido el archivo con el mismo nombre y si hubiera otro igual lo sobrescribe. Por último nos desconectamos del servidor y eliminamos el objeto.

FTP.Disconnect;
FTP.Free;
end;

Como suelo comentar en artículos anteriores los componentes Indy no controlan bien la multitarea, por lo tanto si vamos a subir archivos relativamente grandes recomiendo meter el método Put dentro de un hilo de ejecución, ya que si no es así, mientras que el componente TIdFTP no termine de subir el archivo, nuestra aplicación da el aspecto de estar colgada (no se puede ni mover la ventana).

Tampoco estaría mal mostrar al usuario mediante una barra de progreso el estado de la subida del archivo. Para ello el objeto TIdFtp posee el evento OnWork el cual nos informa de los bytes subidos al servidor. El cambio es sencillo.

Primero creamos el evento OnWork:

procedure TFVentana.FTPWork( Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer );
begin
Barra.Position := AWorkCount div 1024;
end;

Se supone que Barra es un componenete TProgressBar donde vamos acumulando el tamaño del archivo enviado. En este caso he dividido los bytes subidos entre 1024 para que me devuelva la información en kilobytes.

Y ahora asociamos el evento al componente después de crearlo:

FTP := TIdFTP.Create( nil );
FTP.OnWork := FTPWork;

¿Cómo averiguamos el tamaño del archivo para medir el progreso? Muy fácil:

procedure SubirArchivo( sArchivo: String );
var
FTP: TIdFTP;
F: File of byte;
begin
AssignFile( F, sArchivo );
Reset( F );
Barra.Max := FileSize( F ) div 1024;
CloseFile( F );
....

Con esto le decimos a la barra de progreso que la longitud máxima de la misma es la longitud del archivo en kilobytes. Una vez comience a subir el archivo la barra de progreso se va incrementando sola según el evento OnWork.

Y por supuesto nunca se os olvide controlar en todo momento el estado de la conexión, tanto para conectar, subir el archivo o desconectarse del servidor capturando las excepciones oportunas e informando al usuario de lo que ocurre (por ejemplo con una barra de estado en la parte inferior de la ventana).

En el próximo artículo mostraré como descargar un archivo por FTP.

Y lo se, a veces los componentes Indy pueden sacar de quicio a cualquiera.

Pruebas realizadas en Delphi 7.

Publicidad