Categoria:
A data e hora de um arquivo no servidor pode ser lida com as funções de FTP usando basicamente a TIpClientFtp(). Todavia, os servidores da web usam a hora universal UTC 0 (Coordinated Universal Time). Daí é preciso converter a hora da coordenada 0 para a coordenada -3 que é a do Brasil para se obter a data e hora correta em nosso fuso horário. Em [x]Harbour, xBase, usamos a função SECS() que transforma a hora em segundos e a função TSTRING() que transforma de volta para hora.
Portanto, se você tentar comparar a hora do arquivo local com a do servidor que você acabou de fazer upload nunca dará igual sem que você faça a conversão do fuso horário na hora de baixá-lo.
Para obter a lista de arquivos no servidor você usará o método :listFiles() que funciona semelhante à nossa velha e conhecida função DIRECTORY() retornando uma matriz multidimensional com a lista de arquivos.
O problema dessa belezinha de método é que só vem a hora e minuto HH:MM, uma string de 5 caracteres, ao invés de vir completo com os segundos também, string com 8 caracteres HH:MM:SS. Ao menos no meu computador com o meu servidor foi assim. Daí precisei fazer ajustes para mitigar a diferença.
Precisei criar um objeto TURL() primeiramente para usar com o objeto TIpClientFtp() visto que meu nome de usuário das credenciais FTP contém um arroba ("@"), daí deu problema usando direto nela.
Essa rotina abaixo foi tirada de um sistema meu, portanto usa outras funções personalizadas e vai dar erro de "função não existe" se você tentar compilar, mas servirá para fins didáticos e poderá ser aproveitada perfeitamente em outros casos com as devidas substituições.
O exemplo que tenho no manual do xHarbour da função que mostra a barra de progresso de upload e download não funciona porque o terceiro parâmetro não dá o tamanho do arquivo, então temos que obter essa informação para passar para a função.
No exemplo abaixo eu quero saber se a data do arquivo manual.pdf no servidor é mais recente da que eu tenho localmente no computador que roda o sistema. Se for eu baixo.
Sem mais apresentações, vamos lá!
cMANUAL := "manual.pdf" // NOME DO ARQUIVO PARA BAIXAR SE FOR MAIS NOVO
IF FILE(cMANUAL)
MSGRODA("Verificando se o manual existente é o mais recente...", "W+/BG")
// VERIFICA SE HÁ MANUAL MAIS RECENTE
// FTP CREDENTIALS
oURL := TUrl():new()
oUrl:cProto := "ftp"
oUrl:cUserid := "seu nome de usuário FTP" // altere
oUrl:cPassword := "sua senha do FTP" // altere
oUrl:cServer := "seu servidor" // altere
oUrl:nPort := 21
MSGRODA("Abrindo conexão FTP...", "W+/BG")
oFTP := TIpClientFtp():new( oURL ) // ABRE CONEXÃO FTP
IF oFTP:OPEN()
dHELP1 := dHELP2 := hHELP1 := hHELP2 := ""
tHELP2 := 0
// DATA E HORA DO ARQUIVO LOCAL
aLOCAL := DIRECTORY("*.PDF")
X := ASCAN(aLOCAL, {|A| UPPER(A[1]) == UPPER(cMANUAL)})
IF X>0
dHELP1 := aLOCAL[X][3] // DATA DO ARQUIVO
hHELP1 := aLOCAL[X][4] // HORA DO ARQUIVO hh:mm:ss
nSECS1 := SECS( hHELP1 ) // HORÁRIO EM SEGUNDOS
ENDIF
// DATA, HORA E TAMANHO DO ARQUIVO NA NUVEM
MSGRODA("Acessando pasta remota...", "W+/BG")
oFTP:CWD("diretório onde estão os aquivos") // altere
MSGRODA("Obtendo lista de arquivos...", "W+/BG")
aNUVEM := oFTP:listFiles()
X := ASCAN(aNUVEM, {|A| UPPER(A[1]) == UPPER(cMANUAL)})
IF X>0
tHELP2 := aNUVEM[X][2] // TAMANHO DO ARQUIVO
oFTP:exGauge := {|nSENT, nTOTAL, oFTP| FtpProgress(nSENT, nTOTAL, oFTP, tHELP2) } // BARRA DE PROGRESSO CORRIGIDA QUE FUNCIONA
dHELP2 := aNUVEM[X][3] // DATA DO ARQUIVO
hHELP2 := aNUVEM[X][4] // HORA DO ARQUIVO hh:mm
// EQUIPARAR HORAS
hHELP1 := LEFT(hHELP1, LEN(hHELP2) ) // SE REMOTO HH:MM ENTÃO LOCAL HH:MM
// Converter fuso horário UTC 0 para -3
nSECS2 := SECS( hHELP2 )
nUTC3 := (3*3600) // 3h
nSECS2 -= nUTC3 // -3h
IF nSECS2 >= 0
hHELP2 := TSTRING( nSECS2 ) // TRANSFORMA EM HORA
ELSE
// MADRUGADA DO DIA ANTERIOR, VOLTA 1 DIA
dHELP2 -= 1 // VOLTA 1 DIA
hHELP2 := TSTRING( 86400 + nSECS2 ) // TRANSFORMA EM HORA NA FORMA CORRETA, NESSE CASO
nSECS2 := SECS( hHELP2 ) // ATUALIZA nSECS2
ENDIF
ENDIF
nLAG := ABS( nSECS2 - nSECS1 )
IF (nLAG/60) < 2 // TOLERÂNCIA DE LAG: 2min
// DIFERENÇA IRRELEVANTE, ZERA A DIFERENÇA, CONSIDERA IGUAL.
nSECS1 := nSECS2
ENDIF
IF dHELP1 < dHELP2 .OR. (dHELP1 == dHELP2 .AND. nSECS1 < nSECS2 )
nBAIXA := ALERT("Há uma nova versão do manual, baixar agora?", {"Sim", "Não"})
IF nBAIXA = 1
MSGRODA("Iniciando download...", "W+/BG")
IF oFTP:downloadFile( cMANUAL ) // MÉTODO PARA FAZER O DOWNLOAD DO ARQUIVO
MSGRODA("Arquivo baixado com sucesso!", "W+/BG")
ELSE
MSGRODA(oFtp:lastErrorMessage(), "W+/BG")
ENDIF
ENDIF
ELSE
MSGRODA("Você tem o manual mais recente!", "W+/BG")
ENDIF
ELSE
MSGRODA(oFtp:lastErrorMessage(), "W+/BG")
ENDIF
// HELP EXISTE
MSGRODA("Abrindo o manual no leitor padrão de PDF...", "W+/BG")
RUN MANUAL.PDF
ENDIF
Agora a função de progresso readequada:
// Displays a progress bar during file upload/download FUNCTION FtpProgress( nSent, nFIM, oFtp, nSIZE ) LOCAL cProgress LOCAL nRow := Row(), nCol := Col() cFILEDOWN := "Baixando "+ALLTRIM(oFtp:oUrl:cFile)+": " nMAXCOL := MAXCOL() - LEN(cFILEDOWN) cVAZIA := Replicate( Chr(177), nMAXCOL ) cProgress := Replicate( Chr(219), Int( nMAXCOL*nSent/nSIZE ) ) cBAIXANDO := cFILEDOWN + cPROGRESS @ MAXROW(),00 SAY cFILEDOWN + cVAZIA COLOR "W+/BG" @ MAXROW(),00 SAY cBAIXANDO COLOR "W+/BG" IF nSENT = nSIZE @ MAXROW(),00 SAY cFILEDOWN + Replicate( Chr(219), nMAXCOL ) COLOR "W+/BG" // só pra certificar ENDIF SetPos( nRow, nCol ) RETURN .T.
Observe que o parâmetro nFIM é o que deveria ter o tamanho do arquivo, mas sempre é -1, por isso não funcionava. Daí, damos um jeito de obter o tamanho do arquivo e passar para a função no parâmetro nSIZE. Tudo certo!
