Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Problemas bajar archivo (Ftp) (https://www.clubdelphi.com/foros/showthread.php?t=74640)

NEG1414 30-06-2011 19:29:34

Problemas bajar archivo (Ftp)
 
Buenas

Estoy usando el Componente TIdFTP (Indy9) para desecargar un archivo (1k) mediante FTP de la siguiente manera


Código:

  AnsiString PathApp  = ExtractFilePath(Application->ExeName);

  if(!Ftp->Connected())
  {
    Ftp->Host    = "ftp.Miserver.es";
    Ftp->Username = "[email protected]";
    Ftp->Password = "Mipase";
    try
    {
      //Conecto con servidor
      Ftp->Connect(true);
      try
        {

          AnsiString Destino = PathApp+ "123.txt";
          TFileStream *FStream;
          FStream = new TFileStream(Destino,fmCreate);
          Ftp->Get("123.txt",FStream,false);
      }

      ................
      .................

En principio no me da problemas al conectar (o eso creo) El problema surge cuando se realiza el evento Get del Componente... queda en "stand by" bastantes segundos y se produce el siguiente error

Socket error #10054 Connection reset by peer

Que hago mal Gracias

_cero_ 30-06-2011 19:52:56

No le veo mal, aunque me pregunto porque le pasas true a Connect :confused: si hasta donde recuerdo este método solo recibe “void” o “UnicodeString host” o “UnicodeString host, unsigned short puerto”, quizás ahí este tu problema, tampoco entiendo porque descargas el archivo a Stream en lugar de descargarlo directamente, acaso lo usas en memoria?

NEG1414 03-07-2011 18:50:49

Gracias por contestar... y perdona el retraso,he estado fuera....

He probado con

Código:

ftp->Conect()
en principio no da error y se supone que conecta igual...pero sigue dando el mismo error en el evento Get respecto a “UnicodeString host” o “UnicodeString host, unsigned short puerto”,no tengo ni idea de que parametros asignar..:(

Respecto al tema del Fstream...no entiendo muy bien que te refieres con "descargarlo directamente" si es de la siguinete manera:

Código:

AnsiString Destino = PathApp+ "123.txt";
Ftp->Get("123.txt", Destino,false);

me da el error Destination file already exists


Nota: Mediante un programa ftp (cute) no tengo ningun problema a la hora de interactuar con el archivo....

Gracias Otra Vez..

_cero_ 03-07-2011 21:59:02

mmm veamos, te pongo código para que veas como se hace una descarga simple.


Código:

    TIdFTP* ftp1 = new TIdFTP( NULL );

    try {
        ftp1->Username = "xxx";
        ftp1->Password = "yyy";

        ftp1->Host = "localhost"; //Podemos ahorrarnos estas líneas, porque las puedes escribir en conect
        ftp1->Port = 21;          //ejem. ftp1->Connect( "localhost" ); o ftp1->Connect( "localhost", 21 );

        ftp1->Connect();

        ftp1->ChangeDir( "MiCarpeta" ); //En caso de que un archivo no esté en la raíz del ftp

        ftp1->Get(
            "MiArchivo.txt",
            "C:\\MiArchivo.txt", //Ruta del archivo, para que baje directamente
            true, //si quieres que sobre escriba el archivo en caso de que exista
            false //si quieres que resuma la descarga
        );

        ShowMessage( "el qrchivo se descargo." );
        ftp1->Disconnect();
    }
    __finally {
        delete ftp1;
    }

Ahí veras los posibles parámetros que se le pueden dar a Conect, en primera no sé porque el compilador te deja pasar “Conect( true )” quizás por la versión de los componentes (tengo la 10.5.7), pero mejor acostúmbrate a no pasarle nada, por si cambias de versión.

También veras como utilizar get, para descargar directamente, sin necesidad de que declares un Stream, podrás sobrescribir un archivo (con lo que se soluciona el error de “Destination file already exists”), o podrás resumir las descargas, en caso de un fallo de conexión, o si te apetece ponerle pausa y resumen en tu apl, prueba este código en un botón, con los datos de tu ftp y si sigue dando el error que comentaste al principio, habrá que ver la configuración del ftp. Hasta donde recuerdo ese error es porque el ftp te contesta con un paquete reset, e interrumpe la conexión, pero no estoy seguro, por eso lo de probar el código que te dejo.

NEG1414 04-07-2011 20:03:10

Gracias por tu tiempo.....

En primer lugar referente a que Ftp->Connect() acepte el parametro true, tenias razon, es un tema de versiones, yo uso la 9 y los parametros que puedes incluir son (boolAAutoLogin,Int AtimeOut), por consiguiente no puedo usar los parametros UnicodeString host” o “UnicodeString host, unsigned short puerto”....

He implementado tu codigo, pero me ha dado el mismo error (de conexion, el de “Destination file already exists” solucionado) , para descartar que el problema fuera del Hosting, he utilizado otro (tampoco da ningun problema utilizando CuteFTP) y el error ha cambiado lo sigue dando en el componente Get pero ahora es:

Connection Closed GraceFully

Empiezo a sospechar que el error tiene que ver con mi Pc (Cortafuegos,puertos.........) para comprobarlo dejo el mini proyecto (400kb) prueba que que me da el error (los datos del Host son los correctos) Para que alguien lo pruebe y certifique si funciona o no.

http://www.megaupload.com/?d=E8VNFKF2


Gracias..

_cero_ 04-07-2011 21:47:05

Baje y probé tu proyecto y me funciona sin error, lo que me lleva a pensar que el error está en el host, ya que dices que cambiando host te sale “Connection Closed GraceFully” (el cual es un error más común, y en algunos casos despreciable, te dejo este link), y no el otro error “Connection reset by peer” habría que revisar tanto la configuración del host (si tienes control de él), y la configuración de tu maquina (por lo general son los puertos).

En fin para concluir:
1 Si solo te sale “Connection Closed GraceFully” y te conecta y descarga todo sin problemas, habría que considerar el cacharlo e ignorarlo, para que todo quede bien.

2 si te sigue saliendo “Connection reset by peer” revisa los puertos, los privilegios de los usuarios que estas usando para conectarte, en fin la configuración tanto del ftp, como de tu pc, ya que tu código si sirve, y no me dio ningún error.

Estos son puntos que dejo como observaciones.

3 GET ni es un evento ni es un componente, Get es un método, si lo llamas de otra forma confundes al que te lee.

4 procura no usar try y cathc tan despreocupadamente, como todo en un lenguaje de prog, tienen una función determinada, y usarlos indiscriminadamente te puede causar muchos problemas de diferentes magnitudes. Yo use try y finally para asegurarme de que aunque hubiera una excepción se liberar a ftp1, ni más ni menos.

5 todo objeto que crees con Owner = NULL, lo tienes que destruir tú (usando delete), o causaras fugas de memoria, que merman el funcionamiento de tu apl (mientras este ejecutándose ira consumiendo más y más ram), lo digo porque debiste poner un “delete Ftp;” para liberar el componente y quedar todos felices y contentos XXXD. nos vemos

NEG1414 05-07-2011 18:42:38

Gracias por Contestar...

Perfecto, estabas en lo cierto he solucionado la Excepcion (no el error) "Connection Closed GraceFully" como me indica el Hilo que me has recomendado, evitando que salte (indicandolo en las opciones de Depuracion), y me baja el archivo perfectamente.
Seguire indagando el error "Connection reset by peer” que me da usando el otro Hosting y si lo subsano os informare.

He añadido en el Hosting (que funciona) una carpeta ("Principal") y dentro de esta una serie subcarpetas que contienen archivos;he intentado "listarlos" todos y diferenciar cuales son carpetas para luego bajarlos mediante una funcion recursiva , en la red he encotrado y adaptado este codigo (Dix Leo)

Código:

  if(Ftp->Connected())
  {
    Ftp->ChangeDir("Principal");

    std::auto_ptr<TStringList> Lista (new TStringList);
    Ftp->List(Lista.get());

    for (int i=0;i<Ftp->DirectoryListing->Count; ++i)
        {
            TIdFTPListItem*  ListItem = Ftp->DirectoryListing->Items[i];
            String Filename  = ListItem->FileName;

            bool IsDir      = ListItem->ItemType == ditDirectory; //(supongo  que me indica si es una carpeta)             
            ..........................
            .......................... 
        }
    }

A medida que recorro La lista solo alguno de los Filename se corresponden con las Carpetas o Archivos Existentes( no se si es por que me fata un #include en la Cabecera)

Algun Apunte Gracias.

PosData: Tomo noto de tus observaciones.

escafandra 05-07-2011 23:40:55

Quizás puedan interesar tres enlaces sobre descargas de ficheros, 1 (en C), 2(en delphi y C) y 3 (en delphi con WinSock).

En el enlace 2 hace referencia a un hilo que se borro en el último terremoto que azotó al club delphi y que se llevó por delante montones de mensajes :(.


Saludos.

NEG1414 06-07-2011 19:45:03

Gracias por vuestro tiempo ...

NEG1414 06-07-2011 20:11:23

...... He conseguido hacer lo que queria bajarme las carpetas y subcarpetas del Hosting, supongo qur habra una manera mucho mas facil de Hacerlo pero a mi me vale... la pongo por si a alguien le sirve
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{

  Ftp = new TIdFTP(NULL);

  AnsiString PathApp  = ExtractFilePath(Application->ExeName);
  AnsiString CTemp = PathApp + "Temp\\";
  mkdir(CTemp.c_str());

  Ftp->Host    = "host.com";
  Ftp->Username = "1234567";
  Ftp->Password = "*******";

  //Conecto con servidor
  try
  {
    Ftp->Connect();
    if(Ftp->Connected())
    {
      try
        {
          Ftp->ChangeDir("/Principal"); //Carpeta Principal
          //Actualizo//
          NewCarpeta(CTemp);
          //Desconecto
          Ftp->Disconnect();
        }
        catch (...)
        {
          if (MessageDlg("No se han podido actualizar los Datos",
          mtError,TMsgDlgButtons() << mbOK, 0) == mrOk){return;}
        }
    }
  }
  catch (...)
  {
    if (MessageDlg("No ha sido posible establecer la conexion",
    mtError,TMsgDlgButtons() << mbOK, 0) == mrOk){return;}
  }

  delete Ftp;Ftp = NULL;
}

//-----------------------------------------------------------------------//

void  TForm1::NewCarpeta(AnsiString Path)
{


    std::auto_ptr<TStringList> Elementos (new TStringList);
    Ftp->List(Elementos.get());
    int NumElemnt = Ftp->DirectoryListing->Count;
    bool *IsDir = new  bool[NumElemnt];

    //Conozco cuales son sus Subcarpetas
    for (int i=2;i<NumElemnt;i++)
      {
        TIdFTPListItem*  ListItem = Ftp->DirectoryListing->Items[i];
        Elementos->Strings[i] = ListItem->FileName;
        IsDir[i]=ListItem->ItemType == ditDirectory;
      }

    //Copio
    for (int i=2;i<NumElemnt; i++)
        {
            //Si es una SubCarpeta
            if(IsDir[i])
              {
                Ftp->ChangeDir(Elementos->Strings[i]);
                mkdir((Path+Elementos->Strings[i] + "\\").c_str());
                NewCarpeta(Path+Elementos->Strings[i] + "\\");
              }
              else
              {
                //Bajo Archivo
                AnsiString Copia = Path + Elementos->Strings[i];
                Ftp->Get(Elementos->Strings[i],Copia,true); 
              }
        }

  Ftp->ChangeDirUp();
}

Gracias

NEG1414 07-07-2011 21:10:03

He solucionado el error Socket error #10054 Connection reset by peer que me daba en uno de los hosting al querer bajar un archivo....he asignado una conexion pasiva al idFtp de la forma

Código:

Ftp->Passive = true;
y perfecto:)

Nota: Tabajando con los dos hosting me he dado cuenta de que a la hora de cargar la lista de elementos con

Código:

Ftp->List(TSTringListElementos);
Uno de ellos incluye como los elementos "." y ".." (el otro no) es por ello que en el algoritmo del hilo anterior el bucle que recorre los elementos empieza en 2 ya que las posiciones 0 y 1 son las que ocupan estos elementos


La franja horaria es GMT +2. Ahora son las 06:27:23.

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