AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung IOS App Thread Download FTP weißer Bildschirm
Thema durchsuchen
Ansicht
Themen-Optionen

IOS App Thread Download FTP weißer Bildschirm

Ein Thema von oakley · begonnen am 29. Sep 2023 · letzter Beitrag vom 2. Okt 2023
Antwort Antwort
oakley

Registriert seit: 15. Aug 2005
287 Beiträge
 
#1

IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 10:52
Hallo zusammen,

ich bin gerade dabei eine IOS App zu programmieren, die Daten via Unidac aus einer MariaDB holt und dazu Dateien per FTP Download herunter lädt.

FTP Download starte ich in einem sparaten Thread, den Fortschrittsbalken aktualisiere ich per Synchronize.
Ich lade zum Einen Dokumente herunter, zum anderen technische Zeichnungen.

Der Code ist etwas gekürzt, oberhalb werden noch einige andere Dateien geladen aber entweder bleibt der Thread bei den Dokumenten "hängen", zu mindest zeigt er das nach dem Synchronize in meiner Textbox an.
Es kann auch sein, dass er bis zu den Plänen kommt, und dann dort stehen bleibt. Läuft der Thread weiter und die Anzeige wird nicht synchronisiert?
Und Teilweise bekomme ich beim Download der Dokumente plötzlich einen weißen Bildschirm angezeigt.
Ich habe gerade gesehen, dass der weiße Bildschirm beim Laden der Pläne angezeigt wird (oder danach).

Gibt es eigentlich eine verlässiche Methode unter IOS zu prüfen ob eine Internetverbindung verfügbar ist? Der Download soll ja nicht starten wenn man keien Verbindung zum Server hat.

Delphi-Quellcode:
procedure TSingleSyncThread.Execute;

  Procedure DownloadFolder(calledfrom, ARemoteFolder, ALocalFolder: string);
  var
    SubFolders: TStringList;
    I: Integer;
  begin
    ALocalFolder := IncludeTrailingPathDelimiter(ALocalFolder);
    ForceDirectories(ALocalFolder);
    SubFolders := TStringList.Create;
    try
      DM1.FTP1.ChangeDir(ARemoteFolder);
      DM1.FTP1.List;

      TSyncThread.Synchronize(nil,
      procedure
      begin
        CSITEDETFORM.xpbar.Max := DM1.FTP1.DirectoryListing.Count;
        CSITEDETFORM.xpbar.Visible := True;
      end);

      for I := 0 to DM1.FTP1.DirectoryListing.Count-1 do
      begin
        if DM1.FTP1.DirectoryListing[I].ItemType = ditFile then
        begin
          if (ExtractFileExt(DM1.FTP1.DirectoryListing[I].FileName) = '.msg') then Continue;
          TSyncThread.Queue(nil,
          procedure
          begin
            CSITEDETFORM.xpbar.Value := i+1;
          end);
          DM1.FTP1.Get(DM1.FTP1.DirectoryListing[I].FileName, ALocalFolder + DM1.FTP1.DirectoryListing[I].FileName, True, false);
        end
        else if DM1.FTP1.DirectoryListing[I].ItemType = ditDirectory then
        begin
          if (DM1.FTP1.DirectoryListing[I].FileName <> '.') and (DM1.FTP1.DirectoryListing[I].FileName <> '..') then
            SubFolders.Add(DM1.FTP1.DirectoryListing[I].FileName);
            CSITEDETFORM.xpbar.Value := i+1;
        end;
      end;
      for I := 0 to SubFolders.Count-1 do
      begin
        DownloadFolder(calledfrom, ARemoteFolder + '/' + SubFolders[I], ALocalFolder + SubFolders[I]);
      end;
    finally
      SubFolders.Free;
      TSyncThread.Queue(nil,
      procedure
      begin
        CSITEDETFORM.xpbar.Visible := false;
      end);
    end;
  end;

  var ... einige Variablen
  begin
    filestosync := TStringlist.Create;
    try
      CSITEDETFORM.SYNCBOX.Visible := True;
      CSITEDETFORM.BTNSYNC.Enabled := false;
      if not DM1.UniConnection1.Connected then DM1.UniConnection1.Connect;

      DM1.CSITESYNCQUERY.Close;
      DM1.CSITESYNCQUERY.SQL.Text := 'SELECT * from documents WHERE DOC_CUSTFURN = ''5'' AND DOC_REFID = ''' + csitetoload + ''';';
      DM1.CSITESYNCQUERY.Execute;

      TSingleSyncThread.Synchronize(nil,
      procedure
      begin
        CSITEDETFORM.SYNCLABEL.Text := 'Dokumente';
      end);

      if DM1.CSITESYNCQUERY.RecordCount > 0 then //if there is data to sync
      begin
        sqlstring := 'INSERT INTO documents (DOC_REFID, DOC_CUSTFURN, DOC_FILENAME, DOC_PATH, DOC_REMARK, DOC_ADDEDDATE, DOC_PARENT, DOC_LEVEL, DOC_TYPE, DOC_NODEID, DOC_NEWSCAN) VALUES ';
        while not DM1.CSITESYNCQUERY.Eof do
        begin
          docfilename := StringReplace(DM1.esc(DM1.CSITESYNCQUERY.FieldbyName('DOC_PATH').AsString), '\','/', [rfReplaceAll, rfIgnoreCase]);
          docfilename := StringReplace(docfilename, '//192.168.100.5/csitestore/docs/', '', [rfReplaceAll, rfIgnoreCase]);

          sqlstring := sqlstring + '(''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_REFID').AsString + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_CUSTFURN').AsString + ''', ''' + DM1.esc(DM1.CSITESYNCQUERY.FieldbyName('DOC_FILENAME').AsString) + ''','+
                                   '''' + docfilename +
                                   ''', ''' + DM1.esc(DM1.CSITESYNCQUERY.FieldbyName('DOC_REMARK').AsString) + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_ADDEDDATE').AsString + ''',' +
                                   '''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_PARENT').AsString + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_LEVEL').AsString + ''', '+
                                   '''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_TYPE').AsString + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_NODEID').AsString + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('DOC_NEWSCAN').AsString + '''),';
          DM1.CSITESYNCQUERY.Next;
        end;

        sqlstring := Copy(sqlstring,1,(Length(sqlstring)-1)); //get rid of the last ,

        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := 'DELETE FROM documents WHERE DOC_REFID = ''' + csitetoload + ''';';
        DM1.SQLITEQUERY.Execute;

        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := sqlstring;
        DM1.SQLITEQUERY.Execute;

        ftpdirectory := 'csitestore/docs';

        try
          if not DM1.FTP1.Connected then DM1.FTP1.Connect;
          try
            try
              DM1.FTP1.ChangeDir(ftpdirectory + '/' + csitetoload);
              TSingleSyncThread.Synchronize(nil,
              procedure
              begin
                if DirectoryExists(TPath.GetTempPath + '/' + csitetoload) then TDirectory.Delete(TPath.GetTempPath + '/' + csitetoload, True);
              end);

              DownloadFolder('docs', '/home/' + ftpdirectory + '/' + csitetoload , TPath.GetTempPath + '/' + csitetoload);

              TSingleSyncThread.Synchronize(nil,
              procedure
              begin
                TDirectory.Copy(TPath.GetTempPath + '/' + csitetoload, csitedocpath + '/' + csitetoload);
              end);
            except
            On E: Exception do
            begin
              TThread.Synchronize(nil,
              procedure
              begin
              end);
            end;
          end;
          finally
            DM1.FTP1.Disconnect;
            filestosync.clear;
        end;
        except
          On E: Exception do
          begin
            TThread.Synchronize(nil,
            procedure
            begin
              CSITEDETFORM.SYNCLABEL.Text := e.Message;
            end);
          end;
        end;
      end
      else
      begin //if there is nothing to sync
        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := 'DELETE FROM documents WHERE DOC_REFID = ''' + csitetoload + ''';';
        DM1.SQLITEQUERY.Execute;
      end;

      DM1.CSITESYNCQUERY.Close;
      DM1.CSITESYNCQUERY.SQL.Text := 'SELECT * from consite_plans WHERE CSITEPLAN_CSITEID = ''' + csitetoload + ''';';
      DM1.CSITESYNCQUERY.Execute;

      if DM1.CSITESYNCQUERY.RecordCount > 0 then //if there is data to sync
      begin
        TSingleSyncThread.Synchronize(nil,
        procedure
        begin
          CSITEDETFORM.SYNCLABEL.Text := 'Pläne';
        end);

        sqlstring := 'INSERT INTO consite_plans (CSITEPLAN_CSITEID, CSITEPLAN_PLAN, CSITEPLAN_PLAN_ORIGNAME, CSITEPLAN_DESCRIPTION, CSITEPLAN_DATE, CSITEPLAN_PARENT, '+
                     'CSITEPLAN_LEVEL, CSITEPLAN_TYPE, CSITEPLAN_NODEID) VALUES ';

        while not DM1.CSITESYNCQUERY.Eof do
        begin
          docfilename := StringReplace(DM1.esc(DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_PLAN').AsString), '\','/', [rfReplaceAll, rfIgnoreCase]);
          docfilename := StringReplace(docfilename, '//192.168.100.5/csitestore/plans/', '', [rfReplaceAll, rfIgnoreCase]);

          sqlstring := sqlstring + '(''' + DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_CSITEID').AsString + ''', ''' + docfilename + ''', ''' + DM1.esc(DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_PLAN_ORIGNAME').AsString) + ''','+
                                   '''' + DM1.esc(DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_DESCRIPTION').AsString) + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_DATE').AsString + ''',' +
                                   '''' + DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_PARENT').AsString + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_LEVEL').AsString + ''', '+
                                   '''' + DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_TYPE').AsString + ''', ''' + DM1.CSITESYNCQUERY.FieldbyName('CSITEPLAN_NODEID').AsString + '''),';
          DM1.CSITESYNCQUERY.Next;
        end;

        sqlstring := Copy(sqlstring,1,(Length(sqlstring)-1)); //get rid of the last ,

        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := 'DELETE FROM consite_plans WHERE CSITEPLAN_CSITEID = ''' + csitetoload + ''';';
        DM1.SQLITEQUERY.Execute;

        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := sqlstring;
        DM1.SQLITEQUERY.Execute;

        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := 'SELECT * FROM consite_plans WHERE CSITEPLAN_CSITEID = ''' + csitetoload + ''' AND CSITEPLAN_TYPE = ''file'';';
        DM1.SQLITEQUERY.Execute;

        if DM1.SQLITEQUERY.RecordCount > 0 then
        begin
          ftpdirectory := 'csitestore/plans';
          try
            if not DM1.FTP1.Connected then DM1.FTP1.Connect;
            try
              try
                DM1.FTP1.ChangeDir(ftpdirectory + '/' + csitetoload);

                TSingleSyncThread.Synchronize(nil,
                procedure
                begin
                  if DirectoryExists(TPath.GetTempPath + '/' + csitetoload) then TDirectory.Delete(TPath.GetTempPath + '/' + csitetoload, True);
                end);

                DownloadFolder('plans', '/home/' + ftpdirectory + '/' + csitetoload , TPath.GetTempPath + '/' + csitetoload);

                TSingleSyncThread.Synchronize(nil,
                procedure
                begin
                  TDirectory.Copy(TPath.GetTempPath + '/' + csitetoload, csiteplanpath + '/' + csitetoload);
                end);
              except
                On E: Exception do
                begin
                  TSingleSyncThread.Queue(nil,
                  procedure
                  begin
                    CSITEDETFORM.SYNCLABEL.Text := e.Message;
                  end);
                end;
              end;
            finally
              DM1.FTP1.Disconnect;
              filestosync.clear;
            end;
            except
              On E: Exception do
              begin
                TSingleSyncThread.Queue(nil,
                procedure
                begin
                  CSITEDETFORM.SYNCLABEL.Text := e.Message;
                end);
              end;
          end;
        end;
      end
      else
      begin //if there is nothing to sync
        DM1.SQLITEQUERY.Close;
        DM1.SQLITEQUERY.SQL.Text := 'DELETE FROM consite_plans WHERE CSITEPLAN_CSITEID = ''' + csitetoload + ''';';
        DM1.SQLITEQUERY.Execute;
      end;
    except
      On E: Exception do
      begin
        TSingleSyncThread.Synchronize(nil,
        procedure
        begin
          CSITEDETFORM.SYNCLABEL.Text := e.Message;
        end);
      end;
    end;
  finally
    DM1.UniConnection1.Disconnect;
    FreeandNil(filestosync);
  end;

Geändert von oakley (29. Sep 2023 um 11:03 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
665 Beiträge
 
#2

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 11:57
Erstens: du scheinst auf die Oberfläche (Hauptthread) zuzugreifen:

Delphi-Quellcode:
CSITEDETFORM.SYNCBOX.Visible := True;
CSITEDETFORM.BTNSYNC.Enabled := false;
Zweitens: Du benutzt für UniDac keine eigene connection im Thread:

Zitat:
When using UniDAC for creating multithreaded applications, you can use approaches similar to the ones described in the "Multithreaded Delphi Database Queries with dbGo (ADO)" article.
At this, you should take into account, that the correct solution will be to use a separate connection (the TUniConnection component) in each thread. In this case, your application will be thread-safe. You can have infinite amount of queries running through one connection in one thread, but you must not run several queries from several threads through one connection.
https://forums.devart.com/viewtopic.php?t=32233
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
214 Beiträge
 
#3

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 12:08
Hi,

Sorry for bad English, and sorry for this is not a full answer for your question.

Your are going after FTP and missing one critical point, FTP does need another channel, meaning it need another connection (socket), with passive mode the client will request the second channel, but without it the server will make the connection to the client, and i am sure your iOS device doesn't have a static Internet IP, and doesn't utilize UPnP out of the box even if your router does support it, mobile ISP never support such protocol.

On other hand FTP is not secure and can't compete with HTTP in speed for downloading, so i highly recommend to drop FTP and switch either HTTPS, SFTP, SSH or WebDAV, it will be way better and more secure, and will work every time.

RealThinkClient as example will simplify this to few lines of code and take care of all the threading you might need, and will perform brilliantly.

ps: many Open and free WiFi will block any traffic not using port 443, expecting and limiting the traffic to HTTPS, all the mentions protocol above can be on that port, removing all the complication with better speed.
  Mit Zitat antworten Zitat
oakley

Registriert seit: 15. Aug 2005
287 Beiträge
 
#4

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 15:08
Hallo Olli,

mit der separaten UniDacConnection bedeutet, dass ich die dann zur Laufzeit erzeugen muss?

LG

Mirko
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
665 Beiträge
 
#5

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 15:25
Du könntest auch alles auf ein Datenmodul klatschen und die Instanz davon im Thread dynamisch erzeugen. In jedem fall darfst du dann nur vom erzeugenden Thread aus darauf zugreifen.
  Mit Zitat antworten Zitat
oakley

Registriert seit: 15. Aug 2005
287 Beiträge
 
#6

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 17:20
Die liegen schon auf einem Datenmodul aber wie instanziere ich die, das habe ich noch nie gemacht.
Der Thread wird auch im Datenmodul ausgeführt.
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
665 Beiträge
 
#7

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 17:42
Also ich würde alles auf ein Extra-Datenmodul verschieben, dieses in den Projektoptionen nicht automatisch erstellen lassen und dann im Thread


Delphi-Quellcode:
var
  LDM: TDM2;
Begin
  LDM := TDM2.create(nil);
  ...
  Mit Zitat antworten Zitat
oakley

Registriert seit: 15. Aug 2005
287 Beiträge
 
#8

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 17:44
Okay verstehe und dann im Thread Terminate das neue Datenmodul wieder freigeben.
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
665 Beiträge
 
#9

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 29. Sep 2023, 17:53
An Besten mit try finally freigeben
  Mit Zitat antworten Zitat
oakley

Registriert seit: 15. Aug 2005
287 Beiträge
 
#10

AW: IOS App Thread Download FTP weißer Bildschirm

  Alt 2. Okt 2023, 19:24
Hallo zusammen,

ich bin heute dazu gekommen auf dem extra Datenmodul die Verbindungen zu machen und zur Runtime zu instanzieren.
Der weiße Bildschirm kommt nicht mehr.
Ich habe aber definitiv ein Problem mit der FTP übertragung. In der Firewall sehe ich, dass für jede Datei ein neuer Port geöffnet wird, ist das normal?
Ich verwende passiv mode Dataport min 35000 max 36000 .
Wenn ich nur ein paar Dateien herunter lade ist alles okay. Lade ich viel, ca. 50 Dateien unterschiedlicher Größe stürzt die App ab.

LG

Mirko
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:42 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz