Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Desarrollo en Delphi para Android (https://www.clubdelphi.com/foros/forumdisplay.php?f=57)
-   -   ¿Cómo escribir un archivo en un servidor FTP sobre TLS explicito desde ANDROID? (https://www.clubdelphi.com/foros/showthread.php?t=96004)

kenneth_kenneth 14-12-2022 22:58:12

¿Cómo escribir un archivo en un servidor FTP sobre TLS explicito desde ANDROID?
 
Tengo este código que funciona perfectamente en Windows, pero al ejecutar la aplicación en Android, la conexión a FTP es exitosa, pero al escribir el archivo, la aplicación se queda en pausa sin hacer nada.

Cabe señalar que en el servidor FTP, aparece que estoy cargando el archivo como en la imagen:



Este es mi código
Código:

procedure TForm1.Button1Click(Sender: TObject);
begin
    IdFTP:=TIdFTP.Create(nil);
    IdSSLIO:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      IdFTP.Disconnect();
        {$ifdef mswindows}
          idopensslsetlibpath('C:\Users\usuario.empresa\Desktop\FTPSExample\SSL');
        {$endif}
        {$ifdef android}
          idopensslsetlibpath(TPath.GetDocumentsPath);
        {$endif}
        IdSSLIO.SSLOptions.Method:=TIdSSLVersion.sslvSSLv23;
        IdSSLIO.PassThrough:=true;
        IdFTP.IOHandler:=IdSSLIO;
        IdFTP.ListenTimeout:=10000;
        IdFTP.ReadTimeout:=10000;
        IdFTP.TransferTimeout:=10000;
        IdFTP.ConnectTimeout:=10000;
        IdFTP.Passive:=true;
        IdFTP.UseTLS:=TIdUseTLS.utUseExplicitTLS;
        IdFTP.DataPortProtection:=TIdFTPDataPortSecurity.ftpdpsPrivate;

        IdFTP.Host := '(ip_ftp)';
        IdFTP.Username := '(user)';
        IdFTP.Password := '(pass)';
       
        try
        IdFTP.Connect;

        try
            {$ifdef mswindows}
              IdFTP.Put('D:\SeLogro.txt','SeLogro.txt',false);
            {$endif}
            {$ifdef android}
              IdFTP.Put('storage/emulated/0/SeLogro.txt','SeLogro.txt',false);
            {$endif}
              ShowMessage('Ready!');
            finally
              IdFTP.Disconnect();

            end;
        except
        on E : Exception do
        begin
          ShowMessage('Exception class name = '+E.ClassName);
          ShowMessage('Exception message = '+E.Message);
        end;
        end;
end;

Encontré una pregunta similar, pero el código está en Java, ¿será posible hacerlo en Delphi 10.3?
https://stackoverflow.com/questions/...r-explicit-tls

dani36652 14-12-2022 23:49:06

1- En Android el Almacenamiento interno se describe como "/sdcard"
2- Para hacer uso del almacenamiento interno en Delphi, debe otorgar los permisos al almacenamiento
3- Android 11 y superiores es un caso peculiar, para ello le compartí el link a un repositorio para solventar eso.
4- Le sugiero meter todos sus procesos "pesados" en un Thread Y sincronizar todo lo visual dentro de dicho thread (memos, mensajes, texto en labels, etc); resulta que en Android de no hacerlo, su app parecerá congelada y después se le mostrará el mensaje de "MyApp no responde"....
Le sugiero ver el un ejemplo en este link: https://github.com/dani36652/DelphiThreadLoadingDialog

Finalmente; su app pareciera congelarse por que la ruta de guardado no era la correcta (/user/emulated/0)
en lugar de /sdcard o por que no otorgó los permisos al almacenamiento.
Le hago llegar esta corrección esperando le sea de ayuda:

Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
  var
  ThreadFTP: TThread;
begin
 ThreadFTP:= TThread.CreateAnonymousThread(
 procedure
 begin
  IdFTP:=TIdFTP.Create(nil);
  IdSSLIO:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);

  IdFTP.Disconnect();
  {$ifdef mswindows}
  idopensslsetlibpath('C:\Users\usuario.empresa\Desktop\FTPSExample\SSL');
  {$endif}
  {$ifdef android}
  idopensslsetlibpath(TPath.GetDocumentsPath);
  {$endif}
  IdSSLIO.SSLOptions.Method:=TIdSSLVersion.sslvSSLv23;
  IdSSLIO.PassThrough:=true;
  IdFTP.IOHandler:=IdSSLIO;
  IdFTP.ListenTimeout:=10000;
  IdFTP.ReadTimeout:=10000;
  IdFTP.TransferTimeout:=30000;
  IdFTP.ConnectTimeout:=10000;
  IdFTP.Passive:=true;
  IdFTP.UseTLS:=TIdUseTLS.utUseExplicitTLS;
  IdFTP.DataPortProtection:= TIdFTPDataPortSecurity.ftpdpsPrivate;
  IdFTP.Host := '(ip_ftp)';
  IdFTP.Username := '(user)';
  IdFTP.Password := '(pass)';
   try
   IdFTP.Connect;

     try
     {$ifdef mswindows}
     IdFTP.Put('D:\SeLogro.txt','SeLogro.txt',false);
     {$endif}
     {$ifdef android}
     //El almacenamiento interno en Android se describe como /sdcard
     //¡OJO! ACEPTE LOS PERMISOS DE ALMACENAMIENTO Y A PARTIR DE ANDROID 5.0
     //SU APP DEBE PEDIR DICHOS PERMISOS EN TIEMPO DE EJECUCIÓN (ANDROID RUNTIME PERMISSIONS)
     //PARA EL CASO DE ANDROID 11+ NECESITA INSTALAR RAD STUDIO 11 ALEXANDRIA Y APLICAR ESTA
     //SOLUCIÓN QUE DESCRIBO EN EL REPOSITORIO
     //https://github.com/dani36652/Delphi-11-Alexandria-Hacer-uso-del-Almacenamiento-en-Android-11-y-Posteriores
     IdFTP.Put('/sdcard/SeLogro.txt','SeLogro.txt',false);
     {$endif}
      TThread.Synchronize(nil,
      procedure
      begin
      ShowMessage('Ready!');
      end);
     finally
     IdFTP.Disconnect();
     end;
     except
     on E : Exception do
     begin
      TThread.Synchronize(nil,
      procedure
      begin
      ShowMessage('Exception class name = '+E.ClassName);
      ShowMessage('Exception message = '+E.Message);
      end);
     end;
   end;
 end);
 ThreadFTP.FreeOnTerminate:= True;
 ThreadFTP.Start;
end;

kenneth_kenneth 15-12-2022 16:17:55

Hola que tal, ya intenté lo sugerido sin éxito alguno, la respuesta de mi servidor es la misma que la de la imagen adjunta, me dice que esta subiendo el archivo "SeLogro.txt" pero nunca termina y en mi servidor aparece el archivo ".txt" con 0 bytes, tendrás alguna otra idea, creo que ya estoy agotando todas las posibilidades, el celular de donde efectuó las pruebas tiene Android 9, espero sirva de algo y muchas gracias por tu pronta respuesta.

dani36652 16-12-2022 17:28:58

Me parece que Android a diferencia de Windows metió ciertas restricciones con FTP por lo que se recomienda hacer uso de SFTP. Voy a investigarle, probablemente haya que escribir algo en el manifest.xml como para poder conectar mediante http. Si encuentro la solución la comparto lo antes posible.

Casimiro Notevi 16-12-2022 20:20:25

Cita:

Empezado por dani36652 (Mensaje 549582)
1- En Android el Almacenamiento interno se describe como "/sdcard"

La "sdcard" es la tarjeta externa, ahí si tienes que "jugar" con los permisos necesarios.


La franja horaria es GMT +2. Ahora son las 12:39:34.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi