HTTP上传进度跟踪 [英] Uploading HTTP progress tracking

查看:148
本文介绍了HTTP上传进度跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有WPF应用程序我正在写的帖子文件的社交网络之一。
上传自己工作得很好,但我想提供的我走多远的上传一些迹象。

I've got WPF application I'm writing that posts files to one of social networks. Upload itself working just fine, but I'd like to provide some indication of how far along I am with the uploading.

我试过一大堆方法要做到这一点:

I tried a bunch of ways to do this:

1)HttpWebRequest.GetStream方式:​​

1) HttpWebRequest.GetStream method:

using (
 var FS = File.Open(
  localFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    long len = FS.Length;
    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
    request.Method = "POST";
    request.ProtocolVersion = HttpVersion.Version11;
    request.ContentType = "multipart/form-data; boundary=--AaB03x";
    //predata and postdata is two byte[] arrays, that contains
    //strings for MIME file upload (defined above and is not important)
    request.ContentLength = predata.Length + FS.Length + postdata.Length;
    request.AllowWriteStreamBuffering = false;
    using (var reqStream = request.GetRequestStream())
    {
        reqStream.Write(predata, 0, predata.Length);
        int bytesRead = 0;
        int totalRead = 0;
        do
        {
            bytesRead = FS.Read(fileData, 0, MaxContentSize);
            totalRead += bytesRead;
            reqStream.Write(fileData, 0, bytesRead);
            reqStream.Flush(); //trying with and without this
            //this part will show progress in percents
            sop.prct = (int) ((100*totalRead)/len);
        } while (bytesRead > 0);
        reqStream.Write(postdata, 0, postdata.Length);
    }
    HttpWebResponse responce = (HttpWebResponse) request.GetResponse();
    using (var respStream = responce.GetResponseStream())
    {
        //do things
    }
}

2)Web客户端的方式(更短):

2) WebClient way (much shorter):

void UploadFile (url, localFilePath)
{
    ...
    WebClient client = new WebClient();
    client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadPartDone);
    client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadComplete);
    client.UploadFileAsync(new Uri(url), localFilePath);
    done.WaitOne();

    //do things with responce, received from UploadComplete
    JavaScriptSerializer jssSer = new JavaScriptSerializer();
    return jssSer.Deserialize<UniversalJSONAnswer>(utf8.GetString(UploadFileResponce));
    //so on...
    ...
}

void UploadComplete(object sender, UploadFileCompletedEventArgs e)
{
    UploadFileResponce=e.Result;
    done.Set();
}

void UploadPartDone(object sender, UploadProgressChangedEventArgs e)
{
    //this part expected to show progress
    sop.prct=(int)(100*e.BytesSent/e.TotalBytesToSend);
}



3)即使TcpClient的方式:

3) Even TcpClient way:

using (
 var FS = File.Open(
  localFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    long len = FS.Length;
    long totalRead = 0;
    using (var client = new TcpClient(urli.Host, urli.Port))
    {
        using (var clearstream = client.GetStream())
        {
            using (var writer = new StreamWriter(clearstream))
            using (var reader = new StreamReader(clearstream))
            {
                //set progress to 0
                sop.prct = 0;
                // Send request headers
                writer.WriteLine("POST " + urli.AbsoluteUri + " HTTP/1.1");
                writer.WriteLine("Content-Type: multipart/form-data; boundary=--AaB03x");
                writer.WriteLine("Host: " + urli.Host);
                writer.WriteLine("Content-Length: " + (predata.Length + len + postdata.Length).ToString());
                writer.WriteLine();
                //some data for MIME
                writer.Write(utf8.GetString(predata));
                writer.Flush();
                int bytesRead;
                do
                {
                    bytesRead = FS.Read(fileData, 0, MaxContentSize);
                    totalRead += bytesRead;
                    writer.BaseStream.Write(fileData, 0, bytesRead);
                    writer.BaseStream.Flush();
                    sop.prct = (int) ((100*totalRead)/len);
                } while (bytesRead > 0)
                writer.Write(utf8.GetString(postdata));
                writer.Flush();
                //read line of response and do other thigs...
                respStr = reader.ReadLine();
                ...
            }
        }
    }
}

在所有情况下,文件被成功发送到服务器。
但是总是进步看起来是这样的:它从0到100的几秒钟,然后等待,直到文件实际上上传(约5分钟 - 文件为400MB)

In all cases the file was successfully sent to the server. But always progress looks like this: for a few seconds it runs from 0 to 100 and then waits until file actually uploading (about 5 minutes - file is 400MB).

所以我觉得从一个文件中的数据缓冲的地方,我没有跟踪上传,但缓冲数据。 。然后必须等待,直到它的上传

So I think the data from a file is buffered somewhere and I'm tracking not uploading, but buffering data. And then must wait until it's uploaded.

我的问题是:

1)是否有任何方法来跟踪的实际的上传数据?该方法Stream.Write()或同花顺()(这是我读的地方,不适合的NetworkStream工作)没有返回,直到它接收从收到的TCP数据包服务器的确认。

1) Is there any way to track actual uploading data? That the method Stream.Write() or Flush() (which as I read somewhere, does not work for NetworkStream) did not return until it receives confirmation from the server that the TCP packets received.

2),或者我否认缓冲(AllowWriteStreamBUffering为HttpWebRequest的不工作)?

2) Or can I deny buffering (AllowWriteStreamBUffering for HttpWebRequest doesn't work)?

3)又是否有意义进一步走下来

3) And does it make sense to go further "down" and try with Sockets?

更新:

要避免任何怀疑中上显示UI前进的道路,我重写了代码,以日志的文件。
所以,这里是代码:

To avoid any doubts in the way of progress displaying on UI, I rewrote the code to log a file. so, here is code:

using (var LogStream=File.Open("C:\\123.txt",FileMode.Create,FileAccess.Write,FileShare.Read))
using (var LogWriter=new StreamWriter(LogStream))
using (var FS = File.Open(localFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    long len = FS.Length;
    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
    request.Timeout = 7200000; //2 hour timeout
    request.Method = "POST";
    request.ProtocolVersion = HttpVersion.Version11;
    request.ContentType = "multipart/form-data; boundary=--AaB03x";
    //predata and postdata is two byte[] arrays, that contains
    //strings for MIME file upload (defined above and is not important)
    request.ContentLength = predata.Length + FS.Length + postdata.Length;
    request.AllowWriteStreamBuffering = false;
    LogWriter.WriteLine(DateTime.Now.ToString("o") + " Start write into request stream. ");
    using (var reqStream = request.GetRequestStream())
    {
        reqStream.Write(predata, 0, predata.Length);
        int bytesRead = 0;
        int totalRead = 0;
        do
        {
            bytesRead = FS.Read(fileData, 0, MaxContentSize);
            totalRead += bytesRead;
            reqStream.Write(fileData, 0, bytesRead);
            reqStream.Flush(); //trying with and without this
            //sop.prct = (int) ((100*totalRead)/len); //this part will show progress in percents
            LogWriter.WriteLine(DateTime.Now.ToString("o") + " totalRead= " + totalRead.ToString() + " / " + len.ToString());
        } while (bytesRead > 0);
        reqStream.Write(postdata, 0, postdata.Length);
    }
    LogWriter.WriteLine(DateTime.Now.ToString("o") + " All sent!!! Waiting for responce... ");
    LogWriter.Flush();
    HttpWebResponse responce = (HttpWebResponse) request.GetResponse();
    LogWriter.WriteLine(DateTime.Now.ToString("o") + " Responce received! ");
    using (var respStream = responce.GetResponseStream())
    {
        if (respStream == null) return null;
        using (var streamReader = new StreamReader(respStream))
        {
            string resp = streamReader.ReadToEnd();
            JavaScriptSerializer jssSer = new JavaScriptSerializer();
            return jssSer.Deserialize<UniversalJSONAnswer>(resp);
        }
    }
}

和这里是结果(我削减中间):

and here is result (I cut the middle):

2011-11-19T22:00:54.5964408+04:00 Start write into request stream. 
2011-11-19T22:00:54.6404433+04:00 totalRead= 1048576 / 410746880
2011-11-19T22:00:54.6424434+04:00 totalRead= 2097152 / 410746880
2011-11-19T22:00:54.6434435+04:00 totalRead= 3145728 / 410746880
2011-11-19T22:00:54.6454436+04:00 totalRead= 4194304 / 410746880
2011-11-19T22:00:54.6464437+04:00 totalRead= 5242880 / 410746880
2011-11-19T22:00:54.6494438+04:00 totalRead= 6291456 / 410746880
.......    
2011-11-19T22:00:55.3434835+04:00 totalRead= 408944640 / 410746880
2011-11-19T22:00:55.3434835+04:00 totalRead= 409993216 / 410746880
2011-11-19T22:00:55.3464837+04:00 totalRead= 410746880 / 410746880
2011-11-19T22:00:55.3464837+04:00 totalRead= 410746880 / 410746880
2011-11-19T22:00:55.3464837+04:00 All sent!!! Waiting for responce... 
2011-11-19T22:07:23.0616597+04:00 Responce received! 



你可以看到程序认为其上传〜400MB约2秒钟。以及7分钟后文件实际上上传和我收到的反响

as you can see program thinks that it uploaded ~400MB for about 2 seconds. And after 7 minutes file actually uploads and I receive responce.

再次更新:

似乎这是在Windows 7下发生的(不是舒尔约64或86)。
当我运行我的代码乌德XP一切完美和进展表示的绝对正确

Seems to this is happening under WIndows 7 (not shure about x64 or x86). When I run my code uder XP everything works perfectly and progress is shown absolute correctly

推荐答案

这是因为超过一年多这个问题被张贴,但我觉得我的帖子可能是有用的人。

it's more than year since this question was posted, but I think my post can be usefull for someone.

我曾与显示进度同样的问题,像你描述它的表现完全一样。所以我决定用它的HttpClient正确显示上传进度。然后,我遇到有趣的错误 - 当我有小提琴手推出HttpClient的开始表明,像在Web客户端以意想不到的方式的上传进度/ HttpWebRequest的上面,所以我鑫卡特也许这是为什么Web客户端显示的上传进步党没有正确的问题(我想我有它推出)。于是,我与Web客户端再次尝试(不提琴手推出类似的应用程序)和所有的作品,因为它应该,上传进度有正确的价值观。我已经测试在几个电脑采用Win7和XP和在所有情况下进展显示出正确的。

I had the same problem with showing progress and it behaved exactly like you described. So i decided to use HttpClient which shows upload progress correctly. Then I've encountered interesting bug - when I had Fiddler launched HttpClient started to show its upload progress in unexpected way like in WebClient/HttpWebRequest above so I thinked maybe that was a problem of why WebClient showed upload progres not correctly (I think I had it launched). So I tried with WebClient again (without fiddler-like apps launched) and all works as it should, upload progress has correct values. I have tested in on several PC with win7 and XP and in all cases progress was showing correctly.

所以,我认为像小提琴手(可能不仅是一个小提琴手)这样的程序对Web客户端和其他.NET类是如何显示上传进度有些影响。

So, I think that such program like Fiddler (probably not only a fiddler) has some affect on how WebClient and other .net classes shows upload progress.

这个讨论批准它:

HttpWebRequest的提琴手时运行

这篇关于HTTP上传进度跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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