как загрузить большие данные на хост с веб-клиентом - PullRequest
0 голосов
/ 27 сентября 2018

Мне нужна функция для загрузки файла больших данных на сервер в виде HTTP-загрузки с POST от внешнего поставщика услуг.в данный момент я использую следующую функцию weblient, и она работает с небольшими файлами:

_byteReturn = await _webClient.UploadDataTaskAsync(_url, File.ReadAllBytes(@"c:\tmp\test.zip"));

, но в этом случае существует проблема с границей 2 ГБ, а функция ReadAllBytes () считывает все байты в память.Конечно, я мог бы использовать другую функцию веб-клиента

_byteReturn = await _webClient.UploadFileTaskAsync(_url, @"c:\tmp\test.zip"));

, но с этой функцией я получаю HTTP-ошибку 400 от сервера.: / так что попробуйте использовать мой собственный код для загрузки.

using (WebClient _webClient = new WebClient())
{
    _webClient.Headers[HttpRequestHeader.UserAgent] = "Test";
    _webClient.Headers[HttpRequestHeader.CacheControl] = "no-cache";
    _webClient.Headers[HttpRequestHeader.Authorization] = string.Format("Basic {0}", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes("Username") + ":" + ("Password" )));

    using (StreamWriter _output = new StreamWriter(await _webClient.OpenWriteTaskAsync(_url)))
    {

        _output.AutoFlush = true;


        using (FileStream _fileStream = new FileStream(@"c:\tmp\install.esd", FileMode.Open, FileAccess.Read))
        {
            _bytesRead = 0;
            _readByteBuffer = new byte[_bufferLength];
            _bytesToRead = _fileStream.Length;


#if DEBUG

            FileStream _testOutFileStream = new FileStream(_writeTestFileNameZip, FileMode.OpenOrCreate, FileAccess.ReadWrite);
#endif
            do
            {
                _fileStream.Seek(_bytesRead, SeekOrigin.Begin);
                _readCount = _fileStream.Read(_readByteBuffer, 0, _bufferLength);
                _output.Write(_readByteBuffer);

#if DEBUG
                if (_testOutFileStream != null)
                { 
                    _testOutFileStream.Write(_readByteBuffer, 0, _readCount);
                    _testOutFileStream.Flush();
                }
#endif
                _bytesRead += _readCount;
            }
            while (_readCount > 0);

#if DEBUG
            if (_testOutFileStream != null)
                _testOutFileStream.Dispose();
#endif
        }

        if (_output != null)
            _output.Close();
    }
}

пункт «ЭТО РАБОТАЕТ».Я не получаю ошибок во время загрузки и получаю правильный ответ от сервера после завершения загрузки, НО загрузка идет как чертовски быстро (загрузка 1 ГБ с 10 Мбит / с за 10 секунд).

Я считаю,это проблема с кешем, но я не уверен.кто знает в чем проблема?

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

на основе Aydin Adn и моих дополнительных поисков, я нашел окончательное решение.необходимо установить для свойства AllowWriteStreamBuffering значение false.это невозможно с исходным веб-клиентом, но в классе расширения.в моем случае это было очень легко, потому что я уже написал свой собственный веб-клиент для работы с данными ответов.там я переопределил функцию GetWebRequest следующим кодом:

protected override WebRequest GetWebRequest(Uri _uri)
{

    HttpWebRequest _webRequest = base.GetWebRequest(_uri) as HttpWebRequest;

    if (_webRequest != null)
    {
        // no buffer
        _webRequest.AllowWriteStreamBuffering = false;
        // if data size overhanded in constructur(necessary with AllowWriteStreamBuffering ==  false)
        if (this.ContentLength > 0)
            _webRequest.ContentLength = this.ContentLength;
        // if NO data size overhanded in constructur(necessary with AllowWriteStreamBuffering ==  false)
        else
            _webRequest.SendChunked = true;
        // if timeout overhanded in constructur
        if (this.TimeOut > 0)
            _webRequest.Timeout = this.TimeOut * 1000;

        return (_webRequest);
    }
    else
        return (null);
}
0 голосов
/ 27 сентября 2018

Не могли бы вы попробовать приведенный ниже код и сообщить мне, если он исправит его для вас, вам нужно перенастроить ваши переменные / etc ...

string _username = string.Empty;
string _password = string.Empty;
string _url = "http://example.com";
string _writeTestFileNameZip = string.Empty;

using (WebClient _webClient = new WebClient())
{
    _webClient.Headers[HttpRequestHeader.UserAgent] = "Test";
    _webClient.Headers[HttpRequestHeader.CacheControl] = "no-cache";
    _webClient.Headers[HttpRequestHeader.Authorization] = $"{Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_username}:{_password}"))}";


    using (Stream _output = await _webClient.OpenWriteTaskAsync(_url))
    using (FileStream _fileStream = new FileStream(@"c:\tmp\install.esd", FileMode.Open, FileAccess.Read))
    {
        byte[] _readByteBuffer = new byte[1024 * 4];
        long _bytesToRead = _fileStream.Length;
        int _bytesRead = 0;

        _fileStream.Seek(0, SeekOrigin.Begin);

        while ((_bytesRead = await _fileStream.ReadAsync(_readByteBuffer, 0, _readByteBuffer.Length)) > 0)
        {
            await _output.WriteAsync(_readByteBuffer, 0, _bytesRead);
        }
    }

}
...