为什么这个FTP下载没有将下载的数据输出到我的输出文件?

时间:2013-11-05 17:37:34

标签: c# ftp stream iostream ftpwebrequest

我正在编写自己的FTPDownload类,并在改变了一些我试图解决的问题之后遇到了一个问题。

我将在下面粘贴的代码有效地开始下载并运行一段时间,在'main'循环的每次迭代中提取完整的数据数组。我可以肯定地说,对于小文件(例如html中的会议议程),可以快速复制并且看似完全复制 - 但是某些东西仍然很不合适。

正如我们所说,我正在下载一个1.05 gig的文件,而我的下载状态控件正在向我显示325 Megs完成 - 我可以证明这个数据已经通过流收集但是这是事情得到的地方很奇怪...到目前为止,我的输出文件只写了548 KB。

以下方法正在进行数据的收集,计数和编写 - 在我最近的更改之前,它的表现相当不错,除了我打算解决的一些性能问题,将其转换为另一个的扩展系列课程。

class DownloadThread : StreamReader
{
    protected override void Cycle()
    {
        if (this.IsComplete)
        {
            this.FireEvent("OnComplete", new Event(this, "DownloadThread has confirmed completion of the targetted download."));
            this.Stop();
            return;
        }
        else if ((this._InputSource = this.GetResponseStream(this.RemotePath)) == null)
        {
            this.FireEvent("OnException",new Event(this,"DownloadThread could not execute. A Response Stream could not be retrieved from the Input Source '" + this.RemotePath + "'."));
            this.Stop();
            return;
        }
        else
        {
            try
            {
                this._StartTime = DateTime.Now;

                Byte[] Bytes = new Byte[4096];

                while ((this.BytesLastRead = this.Read(Bytes, 0, 4096)) > 0)
                {
                    this.LocalStream.Write(Bytes, 0, DataMetrics.Length(Bytes));
                    this.LocalStream.Flush();

                    this.BytesSinceLast += this.BytesLastRead;
                    this.TotalRead += this.BytesLastRead;

                    this.TriggerProgress();

                    continue;
                }
                return;
            }
            catch (Exception e)
            {
                this.FireEvent("OnException", new Event(this, "An exception was encountered while reading data for the download." + Environment.NewLine + e.Message + Environment.NewLine + e.StackTrace));
                return;
            }
        }
    }

    protected override Stream GetResponseStream(string RemotePath)
    {
        this.Request = (FtpWebRequest)FtpWebRequest.Create(this.RemotePath);

        if (this.Credentials != null)
            this.Request.Credentials = this.Credentials;

        this.Response = (FtpWebResponse)this.Request.GetResponse();

        Stream ResponseStream = this.Response.GetResponseStream();

        return ResponseStream;
    }
}

有些值得注意的事情 - 在任何人得出结论之前 - 是这个'循环'方法是在自己的线程中自动在循环内运行的;并将重复每个'ThreadDelay'毫秒(假设它返回)。

此类中的“LocalStream”变量如下:

    protected Stream _LocalStream = null;

    protected Stream LocalStream
    {
        get
        {
            if (this.LocalFile == null)
                return null;
            else if (this._LocalStream == null)
            {
                if (!this.LocalDirectory.Exists)
                    this.LocalDirectory.Create();

                this._LocalStream = this.LocalFile.OpenWrite();

                return this.LocalStream;
            }
            else
                return this._LocalStream;
        }
    }

我认为这可能会导致一些冲突 - 并确保一些线程安全在我的待办事项清单上,但我目前在这个领域没有遇到任何问题 - 我只是假设有人可能想要采取一瞥。

根据'DownloadThread.Read'方法 - 因为我确定有人会好奇......这是继承自我自己的'StreamReader'类;再次继承自我的'InputReader'类。附属领域包括在内。

    protected Object _InputSource = null;

    public Object InputSource
    {
        get
        {
            return this._InputSource;
        }
    }

    public Stream InputStream
    {
        get
        {
            if (this.InputSource == null)
                return null;
            else
            {
                try
                {
                    return (Stream)this.InputSource;
                }
                catch (Exception)
                {
                    return null;
                }
            }
        }
    }

    public override double Read(byte[] buffer, int offset, int count)
    {
        try
        {
            return this.InputStream.Read(buffer, offset, count);
        }
        catch (Exception e)
        {
            this.Stop();
            this.FireEvent("OnException", new Events.Event(this, "An exception was encountered while reading from the InputStream." + Environment.NewLine + e.Message + Environment.NewLine + e.StackTrace));
            return 0;
        }
    }

现在 - 重申 - 我的问题是,由于某种原因,我收到的数据没有被正确地推送到文件中。我即将完成~1演出下载,因为我正在完成输入,并且到目前为止没有抛出异常并且流没有“分崩离析” - 但我的输出文件只有17兆。

等待另外30秒以完成此下载后,我的1.05 gig文件变成了18兆字节的文件;但我认为上述代码不能正确处理这个问题没有特别的原因。

任何人的建议都会很棒。

2 个答案:

答案 0 :(得分:1)

我认为问题可能出在这行代码中:

this.LocalStream.Write(Bytes, 0, DataMetrics.Length(Bytes));

我假设您的DataMetrics.Length()方法返回错误的字节数,因此我建议您尝试:

this.LocalStream.Write(Bytes, 0, this.BytesLastRead);

代替。

答案 1 :(得分:0)

  

值得注意的是 - 在任何人得出结论之前 - 就是这样   'cycle'方法自动在循环内部运行   线;并将重复每个'ThreadDelay'毫秒(假设它   返回)。

我的第一个猜测是操作系统正在丢弃网卡上的数据,因为它没有主动出列,这就是为什么你得到17mb而不是1GB。