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!
Comentários recentes