2

我有一个 C# 控制台应用程序,它从网站下载文件。这是我的方法:

public bool DownloadFile(string fileUri, string filePath)
{
    using (var response = _GetResponce(fileUri)) {
        if (response.StatusCode != HttpStatusCode.OK) {
            return false;
        } 
        using (var responseStrm = response.GetResponseStream()) {
            using (var fileStrm = new FileStream(filePath, FileMode.OpenOrCreate)) {
            var buffer = new byte[CommonConstants.StreamBufferSize];
            int bytesRead = responseStrm.Read(buffer, 0, CommonConstants.StreamBufferSize);      
            while(bytesRead > 0) {
                fileStrm.Write(buffer, 0, bytesRead);
                bytesRead = responseStrm.Read(buffer, 0, CommonConstants.StreamBufferSize);
            }
        }
    }
}

private HttpWebResponse _GetResponce(string requestedUri, string method = "GET")
{
    var request = (HttpWebRequest)WebRequest.Create(requestedUri);
    request.Method = method;
    request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13";
    request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    request.Headers[HttpRequestHeader.AcceptLanguage] = "ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3";
    request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate";
    request.Headers[HttpRequestHeader.AcceptCharset] = "windows-1251,utf-8;q=0.7,*;q=0.7";
    return (HttpWebResponse)request.GetResponse();
}

我试图增加缓冲区大小,但无济于事。如果我添加线程,它可以提高下载速度吗?

4

2 回答 2

1

您是否尝试过在将更多数据写入文件之前缓冲更多数据?一般来说,您希望尽快轮询套接字——根据我的经验,即使有很多字节可供读取,也只能返回相对较小的一部分,这意味着套接字吞吐量最终与开销有关循环的其余部分,这可能很重要。

试试这个代码,看看你是否得到了可衡量的改进:

using (var fileStrm = new FileStream(filePath, FileMode.OpenOrCreate))
using (var responseStrm = response.GetResponseStream()) {
    const int BufferSize = 1 * 1024 * 1024 + CommonConstants.StreamBufferSize;
    var buffer = new byte[BufferSize];
    int offset, bytesRead;
    do {    // Until we've read everything
        offset = 0;
        do {        // Until the buffer is very nearly full or there's nothing left to read
            bytesRead = responseStrm.Read(buffer, offset, BufferSize - offset);
            offset += bytesRead;
        } while (bytesRead != 0 && offset + CommonConstants.StreamBufferSize < BufferSize);

        // Empty the buffer
        if (offset != 0) {
            fileStrm.Write(buffer, 0, offset);
        }
    } while (bytesRead != 0);
}

此外,如果您接受 gzip 和 zlib 流,则需要打开解压缩(!):

request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
于 2013-06-03T18:18:59.347 回答
1

根据服务器的不同,您可能会在下载包含多个段的文件时获得一些速度。

为此,您可以使用request.AddRange不同的线程来下载相同的文件。请注意,当您将数据写入本地文件时,您必须从正确的偏移量开始。

这是大多数下载管理器所做的事情。

请注意,某些服务器不允许这样做。

于 2013-06-03T18:04:59.253 回答