簡體   English   中英

Stream.CopyTo-如何獲取發送的字節?

[英]Stream.CopyTo - How do I get the sent Bytes?


我嘗試以ftp上載的方式獲得傳輸速度,但是我不知道應該在哪里“獲取”它:

程式碼片段:

FtpWebRequest request = (FtpWebRequest)WebRequest.Create(job.GetDestinationFolder() + "\\" + fileOnlyName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(Manager._user, Manager._password);

using (var requestStream = request.GetRequestStream())
{
     using (var input = File.OpenRead(file))
     {
          //input.CopyToAsync()
          input.CopyTo(requestStream);
          //IS HERE ANY METHOD OR ATTRIBUTE, WHICH SHOWS THE SENT BYTES ?
     }
}
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
response.Close();
}

我已經讀過這段代碼

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write (buffer, 0, read);
    }
}

根據剩下的評論 ,效率不是很高:

請注意,這不是最快的方法。 在提供的代碼段中,您必須等待寫入完成才能讀取新的塊。 異步進行讀寫時,這種等待將消失。 在某些情況下,這會使副本速度快兩倍。 但是,這會使代碼更加復雜,因此,如果速度不是問題,請保持簡單並使用此簡單循環。

如何顯示傳輸速度,例如在chrome或firefox上下載?


編輯:
這是我在您之前(Tien Dinh)回答的嘗試:

 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(job.GetDestinationFolder() + "\\\\" + fileOnlyName); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(Manager._user, Manager._password); using (var requestStream = request.GetRequestStream()) { using (var input = File.OpenRead(file)) { Console.WriteLine(input.Length);//bGroundWorker.ReportProgress(request.) Console.WriteLine(input.Position); while (input.Position != input.Length) { input.CopyToAsync(requestStream); Console.WriteLine(input.Position); //bGroundWorker.ReportProgress( (int) input.Position); } Console.WriteLine(input.Length + "(length)"); Console.WriteLine(input.Position + "(sent)"); //e.Result = input.Position; } } FtpWebResponse response = (FtpWebResponse)request.GetResponse(); Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription); response.Close(); 

如您所見,有一個BackgroundWorker,所以我使用CopyToAsync。

您已經有一個CopyStream方法,只需要提高性能即可。 BufferedStream對此非常有用。 見下文。

我相信您也可以通過使用.net 4中的Async方法來進一步改進它。

public static void CopyStream(Stream input, Stream output, Action<int> totalSent)
{
    BufferedStream inputBuffer = new BufferedStream(input);
    BufferedStream outputBuffer = new BufferedStream(output);
    byte[] buffer = new byte[32768];
    int read;
    int total = 0;
    while ((read = inputBuffer.Read(buffer, 0, buffer.Length)) > 0)
    {
         outputBuffer.Write (buffer, 0, read);
         total += read;
         totalSent(total);
    }
    outputBuffer.Flush();
}

您可以構建自己的流包裝器類,以報告在定義的時間間隔內寫入的字節數:

public class StreamWithProgress : Stream
{
    private readonly TimeSpan interval;
    private readonly long sourceLength;
    private readonly Stopwatch stopwatch = Stopwatch.StartNew();
    private readonly BackgroundWorker worker;

    private int bytesInLastInterval;
    private long bytesTotal;
    private Stream innerStream;

    public override bool CanRead
    {
        get { return this.innerStream.CanRead; }
    }

    public override bool CanSeek
    {
        get { return this.innerStream.CanSeek; }
    }

    public override bool CanWrite
    {
        get { return this.innerStream.CanWrite; }
    }

    public override long Length
    {
        get { return this.innerStream.Length; }
    }

    public override long Position
    {
        get { return this.innerStream.Position; }
        set { this.innerStream.Position = value; }
    }

    public StreamWithProgress(Stream stream, BackgroundWorker worker, long sourceLength, TimeSpan? interval = null)
    {
        if (stream == null)
        {
            throw new ArgumentNullException("stream");
        }

        if (worker == null)
        {
            throw new ArgumentNullException("worker");
        }

        this.interval = interval ?? TimeSpan.FromSeconds(1);
        this.innerStream = stream;
        this.worker = worker;
        this.sourceLength = sourceLength;
    }

    public override void Flush()
    {
        this.innerStream.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return this.innerStream.Read(buffer, offset, count);
    }

    public override int ReadByte()
    {
        return this.innerStream.ReadByte();
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return this.innerStream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        this.innerStream.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        this.innerStream.Write(buffer, offset, count);
        this.ReportProgress(count);
    }

    public override void WriteByte(byte value)
    {
        this.innerStream.WriteByte(value);
        this.ReportProgress(1);
    }

    protected override void Dispose(bool disposing)
    {
        if (this.innerStream != null)
        {
            this.innerStream.Dispose();
            this.innerStream = null;
        }
    }

    private void ReportProgress(int count)
    {
        this.bytesInLastInterval += count;
        this.bytesTotal += count;

        if (this.stopwatch.Elapsed > this.interval)
        {
            double speed = this.bytesInLastInterval / (this.stopwatch.Elapsed.Ticks / (double) this.interval.Ticks);
            double progress = this.bytesTotal / (double) this.sourceLength;
            var progressPercentage = (int) (progress * 100);

            this.worker.ReportProgress(progressPercentage, speed);

            this.bytesInLastInterval = 0;
            this.stopwatch.Restart();
        }
    }
}

您可以這樣使用它:

BackgroundWorker worker = (BackgroundWorker)sender;
WebRequest request = WebRequest.Create("SOME URL");
WebResponse response = request.GetResponse();

using (Stream stream = response.GetResponseStream())
using (var dest = new StreamWithProgress(File.OpenWrite("PATH"), worker, response.ContentLength))
{
    stream.CopyTo(dest);
}

將以當前的進度和速度重復調用BackgroundWorker。 您可以使用存儲最近n個速度並報告平均值的隊列來優化該示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM