2014-12-20 5 views
0


Я стараюсь, чтобы получить скорость передачи данных на ФТП-загрузки, но я не знаю, где я должен "получить" это:

Код-Snippet:
Stream.CopyTo - Как получить отправленные байты?

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(); 
} 

I уже прочитал, что this code

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); 
    } 
} 

не очень эффективно, в соответствии с the comment, что осталось:

Note that this is not the fastest way to do it. In the provided code snippet, you have to wait for the Write to complete before a new block is read. When doing the Read and Write asynchronously this waiting will disappear. In some situation this will make the copy twice as fast. However it will make the code a lot more complicated so if speed is not an issue, keep it simple and use this simple loop.

Как я могу показать скорость передачи данных для загрузки в хроме или светлячок как?


EDIT:
Это то, что я пытался перед вами (Тянь-Динь) ответил:

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.

ответ

1

Вы можете создать свой собственный класс поток оболочки, сообщает число байтов, записанных в определенном интервале:

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 Виль l повторяться с текущим ходом и скоростью. Вы можете уточнить этот пример, используя очередь, в которой хранятся последние n скоростей, и сообщает среднее значение.

+0

Это очень круто, но слишком сложно для меня. Можете ли вы объяснить это чуть позже 'double speed = this.bytesInLastInterval/(this.stopwatch.Elapsed.Ticks/(double) this.interval.Ticks);' – Ismoh

+0

Итак, скорость - это уравнение, которое я, возможно, могу использовать в своем коде который вы можете увидеть в моем редактировании? Или это невозможно с 'input.position' и' input.length'? – Ismoh

+0

Каждый раз, когда что-то записывается в поток, мы отслеживаем количество байтов. Как только наш секундомер превышает наш интервал, мы вычисляем скорость. Пример: Интервал = 1 секунда. Секундомер = 1,1 секунды. BytesInLastInterval = 1100. Очевидно, что мы сделали 1100 байт за 1.1 секунды, поэтому получаем 1100/(1.1/1.0) = 1000 байт в секунду. – Frank

1

У вас уже есть метод CopyStream, просто нужно улучшить производительность. BufferedStream отлично подходит для этого. Смотри ниже.

Я считаю, что Вы также можете улучшить его дальше, используя методы ASync в .net 4.

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(); 
} 
+0

Посмотрите на эту статью http://www.tsjensen.com/blog/post/2014/01/21/BufferedStream-Improves-NET-Sockets-Performance.aspx –

+0

'Действие totalSent' является новым для меня , Как это работает? Это метод? А как насчет 'totalSent (total)'? Это количество отправленных данных? Как я могу получить что-то вроде «12345bytes/s»? Является ли ваш код-фрагмент лучше, чем 'CopyTo'? Извините за все эти вопросы, но я все еще новичок в некоторых вещах. – Ismoh

Смежные вопросы