15

我正在使用 HttpWebRequest 将文件上传到某个服务器,现在的问题是我遇到了速度问题。

我无法获得与浏览器(Mozilla Firefox)相同的上传速度,我获得的速度是我从浏览器获得的速度的 1/5。

这是我的 HttpWebRequest 对象的设置

//headers is a NameValueCollection type object,
//Method is a struct { GET, POST, HEAD }

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
        request.UserAgent = headers["User-Agent"];
        request.KeepAlive = false;
        request.Accept = headers["Accept"];
        request.AllowAutoRedirect = AllowRedirect;
        request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.5");
        request.Method = Method.ToString();
        request.AllowWriteStreamBuffering = false;
        request.ReadWriteTimeout = 60000;

我一直启用的一些全局选项

        ServicePointManager.Expect100Continue = false;
        ServicePointManager.DefaultConnectionLimit = 200;
        ServicePointManager.MaxServicePointIdleTime = 2000;
        ServicePointManager.MaxServicePoints = 1000;
        ServicePointManager.SetTcpKeepAlive(false, 0, 0);

我如何以块的形式发送文件...

            if (PostMethod == PostType.MultiPart && uploadFiles.Count > 0)
            {
                for (int i = 0; i < uploadFiles.Count; i++)
                {
                    string fileParam = uploadFiles.GetKey(i);
                    string tmpFilename = uploadFiles.Get(i);
                    string tmpData =
                    string.Format(
                        "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", boundary, fileParam, Path.GetFileName(tmpFilename), MimeType.GetMimeByExtension(Path.GetExtension(tmpFilename)));
                    byte[] tmpBytes = Encoding.Default.GetBytes(tmpData);
                    writer.Write(tmpBytes, 0, tmpBytes.Length);
                    bSent += tmpBytes.Length;

                    arg.Progress = (int)(bSent * 100 / totalBytes);
                    arg.Speed = (bSent / sw.Elapsed.TotalSeconds);
                    OnProgress(arg);

                    //write the file
                    int fileBytesRead;

                    FileStream fileStream = File.Open(tmpFilename, FileMode.Open, FileAccess.Read, FileShare.Read);
// buffer size = 8192
                    while ((fileBytesRead = fileStream.Read(buffer, 0, BUFFER_SIZE)) > 0) 

                    {
                        writer.Write(buffer, 0, fileBytesRead);
                        bSent += fileBytesRead;

                        int timeNow = Environment.TickCount;
                        if (timeNow - lastTime >= 500)
                        {
                            lastTime = timeNow;
                            arg.Progress = (int)(bSent * 100 / totalBytes);
                            arg.Speed = (bSent / sw.Elapsed.TotalSeconds);
                            OnProgress(arg);
                        }
                    }

                    tmpBytes = Encoding.Default.GetBytes("\r\n");
                    writer.Write(tmpBytes, 0, tmpBytes.Length);
                    bSent += tmpBytes.Length;

                    arg.Progress = (int)(bSent * 100 / totalBytes);
                    arg.Speed = (bSent / sw.Elapsed.TotalSeconds);
                    OnProgress(arg);

                }
            }

我很乐意达到浏览器上传速度的 75%。

4

3 回答 3

7

我通过搜索这个网站找到了答案。它似乎是".NET HttpWebRequest Speed vs Browser"的副本。

从那里发布的答案:

“第一次请求页面时,.net 会尝试检测代理设置。解决方案是传入一个空的 WebProxy 对象。这样它只会连接到远程服务器,而不是自动检测代理服务器。” -马科斯

尝试添加

    request.Proxy = new WebProxy();
于 2013-03-09T03:24:23.860 回答
2

两件事情。

  1. 您通过分块破坏了 TCP/IP 堆栈的目的。TCP/IP 旨在处理近乎异步的数据传输。它将自己进行分块并继续发送块,直到完成或达到其最大未确认块数。如果达到最大块数,它将等待 ACK(确认)继续 - 类似于信号量意识形态期望释放可以“堆叠”,AKA 单个 ACK​​ 包含它收到的最后一个点并且可以“释放” /acknowledge 多个块数据包) - 或请求超时。

    通过自己分块,必须完全确认每个块才能发送更多数据,因此您增加了开销。您仍在使用相同的连接,但实际上是在发出多个单独的请求。此外,如果 TCP/IP 块大小不是您的块大小的除数 (YOUR_CHUNK_SIZE % TCP_IP_CHUNK_SIZE != 0),那么您将留下一个延迟的 TCP/IP 块,该块必须超时并解析为伪 ACK;下次它可以在下一个块中得到确认。

  2. 2.

另一个可能影响性能的选项是使用UseNagleAlgorithm 属性。当此属性设置为true时,TCP/IP 将尝试对 HTTP 连接使用 TCP Nagle 算法。Nagle 算法在发送 TCP 数据包时聚合数据。在通过网络发送数据之前,它将小消息序列累积成较大的 TCP 数据包。使用 Nagle 算法可以优化网络资源的使用,尽管在某些情况下性能也会降低。通常对于恒定的大容量吞吐量,使用 Nagle 算法实现性能改进。但是对于较小吞吐量的应用程序,可能会看到性能下降。

应用程序通常不需要更改设置为true的UseNagleAlgorithm属性的默认值。但是,如果应用程序使用低延迟连接,则将此属性设置为false可能会有所帮助。

来自 MSDN:HttpWebRequest 类 (System.Net)

于 2013-03-14T20:47:50.900 回答
1

这是我们可以提高上传速度的各种选项:-

http://bytes.com/topic/asp-net/answers/440179-how-speed-up-file-upload-2-0-a

在大文件的配置文件中使用它:---

把这个写在 web config system.web>

httpRuntime maxRequestLength="2097151"

这可能有助于在 IIS 7.0 中找到解决方案

把这个写在 web config system.web>httpModules

**add name="ITHitPutUploadProgressAndResumeModule" type="ITHit.WebDAV.Server.ResumableUpload.PutUploadProgressAndResumeModule, ITHit.WebDAV.Server"**
于 2013-03-14T12:46:37.187 回答