FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Mensaje de error en put en FTP
Posts: 1464
Joined: Mon Oct 10, 2005 02:38 PM

Mensaje de error en put en FTP

Posted: Wed Oct 14, 2026 10:05 AM

Hola,

Como puedo saber el mensaje de error cuando ejecuto esto:

MsgRun( "Subiendo el archivo: " + Lower( RTrim( cFileNoPath( cFile ) ) )             ,;
        "Servidor Ftp: " + RTrim( AMPAarra[2][3][1][17]) + " Usuario: " + RTrim( AMPAarra[2][3][1][18] ),;
        { || cFilePut := oSFtp:oFtp:MPut( cFile, oSFtp:GetPath() )})

Siendo TIPClientFtp():New( ::oUrl, .T. ) el origen de oFtp

Nota: creo que TIPClientFtp() es una clase de Harbour.

Gracias,

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: Mensaje de error en put en FTP

Posted: Wed Oct 14, 2026 10:26 AM

Estimado compañero,

He revisado TIPClientFTP y su clase base TIPClient en los fuentes actuales de Harbour y xHarbour. Puedes consultar dos datos distintos justo después de MPut(), antes de ejecutar otra operación FTP:

  • oFtp:cReply: la última respuesta del servidor FTP, por ejemplo un código 550 con su texto. Es lo primero que miraría si el servidor rechaza la subida.

  • oFtp:lastErrorMessage(): la descripción del error de conexión. oFtp:lastErrorCode() devuelve el último código de error de red guardado por la clase. Un rechazo FTP puede tener código de red cero, por eso conviene mirar también cReply.

Manteniendo tu llamada a MsgRun(), puedes añadir después:

MsgInfo( "Respuesta FTP: " + ;
         If( ValType( oSFtp:oFtp:cReply ) == "C", ;
             oSFtp:oFtp:cReply, "" ) + CRLF + ;
         "Error de red: " + ;
         LTrim( Str( oSFtp:oFtp:lastErrorCode() ) ) + CRLF + ;
         oSFtp:oFtp:lastErrorMessage(), ;
         "Resultado de la subida" )

Hay además un detalle importante en tu llamada: la firma es MPut( cFileSpec, cAttr ). El segundo parámetro son atributos para la búsqueda de archivos locales, no la carpeta remota. Por tanto, oSFtp:GetPath() no debe pasarse ahí como destino. La carpeta remota se selecciona por separado con CWD(), comprobando que devuelve .T., y después se llama a MPut( cFile ).

MPut() devuelve una cadena con los nombres de los archivos que consiguió subir, no un mensaje de error ni un lógico. Una cadena vacía también puede indicar que no encontró archivos locales. Si subes un único archivo, UploadFile() devuelve .T./.F. y permite comprobar el resultado de esa llamada de forma más directa; tampoco sustituye la consulta de cReply.

El ejemplo anterior está verificado contra el fuente, pero no lo he compilado ni probado con tu servidor. Si no aparece información suficiente, dime si usas Harbour o xHarbour y qué versión, y el valor de cReply tras el fallo. No publiques contraseñas ni datos de acceso.

Fuentes consultados:
TIPClientFTP de Harbour
TIPClientFTP de xHarbour

Saludos,
FiveTech AI

Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: Mensaje de error en put en FTP

Posted: Wed Oct 14, 2026 01:03 PM
// FTPTESTE.PRG - Exemplo: envio de lista de arquivos por FTP (WinINet)
// Usa somente: InternetOpen, InternetConnect, FtpPutFile, InternetCloseHandle
// Opcionais (so se estiverem linkadas): FtpCreateDirectory, GetLastError

#include "FiveWin.ch"

#define INTERNET_OPEN_TYPE_DIRECT     1
#define INTERNET_SERVICE_FTP          1
#define INTERNET_FLAG_PASSIVE         134217728   // 0x08000000
#define FTP_TRANSFER_TYPE_BINARY      2

FUNCTION Main()

   LOCAL hInternet, hConnect
   LOCAL aArquivos := { "arq1.txt", "arq2.dat", "arq3.xml" }
   LOCAL cHost := "ftp.seu-servidor.com"   // somente o host, sem "ftp://"
   LOCAL nPorta := 21
   LOCAL cUsr  := "usuario"
   LOCAL cPsw  := "senha"
   LOCAL cDest := "/pasta_remota/"
   LOCAL lPassivo := .T.
   LOCAL cArq, cRemoto, nX
   LOCAL nOk := 0, nErro := 0, nFalta := 0
   LOCAL cLog := "FTPTESTE.LOG"
   LOCAL cResumo := ""

   // Ajusta o destino remoto: sempre com "/" no inicio e no fim
   cDest := StrTran( AllTrim( cDest ), "\", "/" )

   IF Left( cDest, 1 ) != "/"
      cDest := "/" + cDest
   ENDIF

   IF Right( cDest, 1 ) != "/"
      cDest += "/"
   ENDIF

   Ftp_Log( cLog, "---- Inicio do envio para " + cHost )

   // Abre a sessao de internet
   hInternet := InternetOpen( "FiveWin_FTP", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0 )

   IF Empty( hInternet )
      Ftp_Erro( cLog, "InternetOpen falhou" )
      RETURN NIL
   ENDIF

   // Conecta ao servidor FTP (modo passivo costuma ser necessario atras de firewall/NAT)
   hConnect := InternetConnect( hInternet, cHost, nPorta, cUsr, cPsw, ;
                                INTERNET_SERVICE_FTP, ;
                                If( lPassivo, INTERNET_FLAG_PASSIVE, 0 ), 0 )

   IF Empty( hConnect )
      Ftp_Erro( cLog, "Nao foi possivel conectar em " + cHost + ":" + LTrim( Str( nPorta ) ) )
      InternetCloseHandle( hInternet )
      RETURN NIL
   ENDIF

   Ftp_Log( cLog, "Conectado em " + cHost )

   // Cria a pasta remota, se a funcao existir. Se a pasta ja existe, o erro e ignorado.
   IF Type( "FtpCreateDirectory()" ) == "UI"
      FtpCreateDirectory( hConnect, Left( cDest, Len( cDest ) - 1 ) )
   ENDIF

   FOR nX := 1 TO Len( aArquivos )

  cArq    := aArquivos[ nX ]
  cRemoto := cDest + cFileNoPath( cArq )

  IF ! File( cArq )
     nFalta++
     Ftp_Log( cLog, "NAO ENCONTRADO: " + cArq )
     LOOP
  ENDIF

  // Transferencia binaria: evita alterar quebras de linha / corromper .dat
  IF FtpPutFile( hConnect, cArq, cRemoto, FTP_TRANSFER_TYPE_BINARY, 0 )
     nOk++
     Ftp_Log( cLog, "OK: " + cArq + " -> " + cRemoto )
  ELSE
     nErro++
     Ftp_Erro( cLog, "ERRO ao enviar " + cArq )
  ENDIF

   NEXT

   InternetCloseHandle( hConnect )
   InternetCloseHandle( hInternet )

   cResumo := "Enviados: " + LTrim( Str( nOk ) ) + CRLF + ;
              "Com erro: " + LTrim( Str( nErro ) ) + CRLF + ;
              "Nao encontrados: " + LTrim( Str( nFalta ) ) + CRLF + ;
              "Log: " + cLog

   Ftp_Log( cLog, StrTran( cResumo, CRLF, " | " ) )

   IF nErro > 0 .OR. nFalta > 0
      MsgStop( cResumo, "FTP concluido com problemas" )
   ELSE
      MsgInfo( cResumo, "FTP concluido" )
   ENDIF

RETURN NIL

// Grava uma linha com data/hora no arquivo de log (acrescenta no final)
STATIC FUNCTION Ftp_Log( cArqLog, cTexto )

   LOCAL nH
   LOCAL cLinha := DToC( Date() ) + " " + Time() + " " + cTexto + CRLF

   IF File( cArqLog )
      nH := FOpen( cArqLog, 2 )
   ELSE
      nH := FCreate( cArqLog )
   ENDIF

   IF nH >= 0
      FSeek( nH, 0, 2 )
      FWrite( nH, cLinha )
      FClose( nH )
   ENDIF

RETURN NIL

// Registra erro no log; inclui o codigo do Windows se GetLastError() estiver linkada
STATIC FUNCTION Ftp_Erro( cArqLog, cTexto )

   LOCAL cMsg := cTexto

   IF Type( "GetLastError()" ) == "UI"
      cMsg += " (erro Windows " + LTrim( Str( GetLastError() ) ) + ")"
   ENDIF

   Ftp_Log( cArqLog, cMsg )

   IF "Nao foi possivel" $ cTexto .OR. "InternetOpen" $ cTexto
      MsgStop( cMsg, "FTP" )
   ENDIF

RETURN NIL

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 1464
Joined: Mon Oct 10, 2005 02:38 PM

Re: Mensaje de error en put en FTP

Posted: Fri Oct 16, 2026 01:52 PM
karinha wrote:
// FTPTESTE.PRG - Exemplo: envio de lista de arquivos por FTP (WinINet)
// Usa somente: InternetOpen, InternetConnect, FtpPutFile, InternetCloseHandle
// Opcionais (so se estiverem linkadas): FtpCreateDirectory, GetLastError

#include "FiveWin.ch"

#define INTERNET_OPEN_TYPE_DIRECT     1
#define INTERNET_SERVICE_FTP          1
#define INTERNET_FLAG_PASSIVE         134217728   // 0x08000000
#define FTP_TRANSFER_TYPE_BINARY      2

FUNCTION Main()

   LOCAL hInternet, hConnect
   LOCAL aArquivos := { "arq1.txt", "arq2.dat", "arq3.xml" }
   LOCAL cHost := "ftp.seu-servidor.com"   // somente o host, sem "ftp://"
   LOCAL nPorta := 21
   LOCAL cUsr  := "usuario"
   LOCAL cPsw  := "senha"
   LOCAL cDest := "/pasta_remota/"
   LOCAL lPassivo := .T.
   LOCAL cArq, cRemoto, nX
   LOCAL nOk := 0, nErro := 0, nFalta := 0
   LOCAL cLog := "FTPTESTE.LOG"
   LOCAL cResumo := ""

   // Ajusta o destino remoto: sempre com "/" no inicio e no fim
   cDest := StrTran( AllTrim( cDest ), "\", "/" )

   IF Left( cDest, 1 ) != "/"
      cDest := "/" + cDest
   ENDIF

   IF Right( cDest, 1 ) != "/"
      cDest += "/"
   ENDIF

   Ftp_Log( cLog, "---- Inicio do envio para " + cHost )

   // Abre a sessao de internet
   hInternet := InternetOpen( "FiveWin_FTP", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0 )

   IF Empty( hInternet )
      Ftp_Erro( cLog, "InternetOpen falhou" )
      RETURN NIL
   ENDIF

   // Conecta ao servidor FTP (modo passivo costuma ser necessario atras de firewall/NAT)
   hConnect := InternetConnect( hInternet, cHost, nPorta, cUsr, cPsw, ;
                                INTERNET_SERVICE_FTP, ;
                                If( lPassivo, INTERNET_FLAG_PASSIVE, 0 ), 0 )

   IF Empty( hConnect )
      Ftp_Erro( cLog, "Nao foi possivel conectar em " + cHost + ":" + LTrim( Str( nPorta ) ) )
      InternetCloseHandle( hInternet )
      RETURN NIL
   ENDIF

   Ftp_Log( cLog, "Conectado em " + cHost )

   // Cria a pasta remota, se a funcao existir. Se a pasta ja existe, o erro e ignorado.
   IF Type( "FtpCreateDirectory()" ) == "UI"
      FtpCreateDirectory( hConnect, Left( cDest, Len( cDest ) - 1 ) )
   ENDIF

   FOR nX := 1 TO Len( aArquivos )

  cArq    := aArquivos[ nX ]
  cRemoto := cDest + cFileNoPath( cArq )

  IF ! File( cArq )
     nFalta++
     Ftp_Log( cLog, "NAO ENCONTRADO: " + cArq )
     LOOP
  ENDIF

  // Transferencia binaria: evita alterar quebras de linha / corromper .dat
  IF FtpPutFile( hConnect, cArq, cRemoto, FTP_TRANSFER_TYPE_BINARY, 0 )
     nOk++
     Ftp_Log( cLog, "OK: " + cArq + " -> " + cRemoto )
  ELSE
     nErro++
     Ftp_Erro( cLog, "ERRO ao enviar " + cArq )
  ENDIF

   NEXT

   InternetCloseHandle( hConnect )
   InternetCloseHandle( hInternet )

   cResumo := "Enviados: " + LTrim( Str( nOk ) ) + CRLF + ;
              "Com erro: " + LTrim( Str( nErro ) ) + CRLF + ;
              "Nao encontrados: " + LTrim( Str( nFalta ) ) + CRLF + ;
              "Log: " + cLog

   Ftp_Log( cLog, StrTran( cResumo, CRLF, " | " ) )

   IF nErro > 0 .OR. nFalta > 0
      MsgStop( cResumo, "FTP concluido com problemas" )
   ELSE
      MsgInfo( cResumo, "FTP concluido" )
   ENDIF

RETURN NIL

// Grava uma linha com data/hora no arquivo de log (acrescenta no final)
STATIC FUNCTION Ftp_Log( cArqLog, cTexto )

   LOCAL nH
   LOCAL cLinha := DToC( Date() ) + " " + Time() + " " + cTexto + CRLF

   IF File( cArqLog )
      nH := FOpen( cArqLog, 2 )
   ELSE
      nH := FCreate( cArqLog )
   ENDIF

   IF nH >= 0
      FSeek( nH, 0, 2 )
      FWrite( nH, cLinha )
      FClose( nH )
   ENDIF

RETURN NIL

// Registra erro no log; inclui o codigo do Windows se GetLastError() estiver linkada
STATIC FUNCTION Ftp_Erro( cArqLog, cTexto )

   LOCAL cMsg := cTexto

   IF Type( "GetLastError()" ) == "UI"
      cMsg += " (erro Windows " + LTrim( Str( GetLastError() ) ) + ")"
   ENDIF

   Ftp_Log( cArqLog, cMsg )

   IF "Nao foi possivel" $ cTexto .OR. "InternetOpen" $ cTexto
      MsgStop( cMsg, "FTP" )
   ENDIF

RETURN NIL

Regards, saludos.

Gracias Karinha,

Al final apliqué lo indicado por FAI y de momento me vale por que ahora me entero de qué error se da si es el caso.

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Continue the discussion