Pregunta

Estoy tratando de descargar archivos desde un servidor FTP usando C # y FtpWebRequest. Puedo conseguir los bytes utilizando BinaryReader, pero cuando trato de leer la secuencia utilizando br.ReadBytes (int), me sale un error que BinaryReader no soporta operaciones de búsqueda.

¿Alguien sabe cuál es la mejor para leer los bytes para que pueda escribir en un archivo?

Aquí está el método completo:

    public void DownloadFile(String fileName)
    {
        Logger.Info("starting to download file: " + fileName);

        try
        {
            var downloadFileRequest = (FtpWebRequest)WebRequest.Create(FtpServer + "//" + fileName);
            downloadFileRequest.Credentials = new NetworkCredential(FtpUsername,FtpPassword);
            downloadFileRequest.Method = WebRequestMethods.Ftp.DownloadFile;
            downloadFileRequest.UseBinary = true;

            ServicePoint sp = downloadFileRequest.ServicePoint;
            sp.ConnectionLimit = 2;

            Logger.Info("getting ftp response for download file for " + fileName);

            try
            {
                var downloadResponse = (FtpWebResponse)downloadFileRequest.GetResponse();

                Logger.Info("getting ftp response stream for " + fileName);

                try
                {
                    Stream downloadStream = downloadResponse.GetResponseStream();

                    Logger.Info("File Download status: {0}", downloadResponse.StatusDescription.Trim());

                    Logger.Info("getting binary reader for " + fileName);

                    try
                    {
                       using ( var downloadReader = new BinaryReader(downloadStream))
                       {
                           String destinationFilePath= Path.Combine(LocalFolder, fileName);

                           Logger.Info("writing response stream to " + destinationFilePath);

                           try
                           {
                               using (var downloadWriter = new BinaryWriter(System.IO.File.Open(destinationFilePath, FileMode.Create)))
                               {
                                   downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));
                               }

                               Logger.Info("successfully saved " + destinationFilePath);

                            }
                            catch (Exception ex)
                            {
                                Logger.Info("could not save " + destinationFilePath+ " b/c: " + ex.Message);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Info("could not read " + fileName + " b/c: " + ex.Message);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Info("could not open download stream for " + fileName + " b/c: " + ex.Message);
                }
                finally
                {
                    downloadResponse.Close();
                }
            }
            catch (Exception ex)
            {
                Logger.Info("could not get ftp response stream for " + fileName + " b/c: " + ex.Message);
            }
        }
        catch (Exception ex)
        {
            Logger.Info("could not get ftp request stream for " + fileName + " b/c: " + ex.Message);
        }
    }

Esto se ejecuta como parte de un servicio continuo, por lo que no quiere tirar errores que se detenga el servicio. En cambio, estoy escribiendo en un registro. Estos son los contenidos del registro de este método:

2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|starting to download file: 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|getting ftp response for download file for 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|getting ftp response stream for 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|File Download status: 125 Data connection already open; Transfer starting.
2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|getting binary reader for 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|writing response stream to C:\\Resumes\\2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6951|INFO|xxx.Web.Controllers.FtpController|could not save C:\\Resumes\\2009-10-06155728Z_metadata.txt b/c: This stream does not support seek operations.

He estado trabajando en este camino demasiado largo, por lo que cualquier ayuda se agradece!

Gracias !!

¿Fue útil?

Solución

No se debe confiar en Stream.Length, es posible que podría estar equivocado. Sólo tiene que leer todos los bytes en un bucle while hasta que no hay más bytes a leer.

MemoryStream ms = new MemoryStream();
byte[] chunk = new byte[4096];
int bytesRead;
while ((bytesRead = downloadStream.Read(chunk, 0, chunk.Length)) > 0)
{
     ms.Write(chunk, 0, bytesRead);
}

A partir de ahí, todos los datos de lectura se encuentra en la MemoryStream, y se puede inicializar el BinaryReader con eso.

Otros consejos

respuesta

de Darkassassin funciona muy bien! Aquí está el código por fin llegué a trabajar antes de que viera su puesto. Es un poco diferente de b / c que escribe directamente al archivo en vez de a la secuencia de memoria.

He sustituido esta línea:

downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));

con esto:

var buffer = new byte[BufferSize];
int readCount = downloadStream.Read(buffer, 0, BufferSize);
while (readCount > 0)
{
    downloadWriter.Write(buffer, 0, readCount);
    readCount = downloadStream.Read(buffer, 0, BufferSize);
}

(BufferSize = 4096)

Gracias de nuevo por la ayuda rápida !!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top