Stream.CopyTo - 如何获取发送的字节? [英] Stream.CopyTo - How do I get the sent Bytes?

查看:139
本文介绍了Stream.CopyTo - 如何获取发送的字节?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我尝试在ftp-upload上获得传输速度,但我不知道应该从哪里获得它:



代码片段:

  FtpWebRequest请求=(FtpWebRequest)WebRequest.Create .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);
//是否有任何方法或属性,显示发送字节?
}
}
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 = input.Read(buffer,0,buffer.Length))> 0)

output.Write(buffer,0,read); b






$ b

根据留下的评论


请注意,这不是最快的方法。在提供的代码片段中,您必须等待写入完成才能读取新块。当进行异步读写时,此等待将消失。在某些情况下,这会使复制速度快两倍。然而,它会使代码变得更加复杂,所以如果速度不是问题,请保持简单并使用这个简单的循环。


如何在chrome或firefox中显示传输速度?
编辑:

这就是我在你之前所尝试的(田亭)回答:


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

使用(var requestStream = request.GetRequestStream())
使用(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。$ b $您可以构建自己的流封装类,用于报告以定义的时间间隔写入的字节数:

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

private int bytesInLastInterval;
私有长bytesTotal;
私有流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长度
{
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)
{
抛出新的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);


保护覆盖无效Dispose(bool处置)
{
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();



$ / code $ / pre

你可以像这样使用它:

  BackgroundWorker worker =(BackgroundWorker)sender; 
WebRequest请求= 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个速度并报告平均值的队列来优化该示例。



I try to get the transfer speed at a ftp-upload, but I don't know where I should "get" it:

Code-Snippet:

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 already read that 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);
    }
}

isn't really efficient, according to the comment that was left:

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.

How can I show the transfer speed like a download at chrome or firefox ?


EDIT:
This is what I tried before you (Tien Dinh) answered:

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

As you can see there is a BackgroundWorker so that I use CopyToAsync.

解决方案

You could build your own stream wrapper class that reports the number of bytes written in a defined interval:

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

You would use it like this:

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

The BackgroundWorker will be called repeatedly with the current progress and speed. You could refine that example using a queue that stores the last n speeds and reports a mean value.

这篇关于Stream.CopyTo - 如何获取发送的字节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆