Ответ 1
Если вы используете WebClient.DownloadFile, вы можете сохранить его непосредственно в файл.
Мне нужно загрузить большой файл (2 GB) через HTTP в консольном приложении С#. Проблема в том, что после примерно 1,2 GB в приложении заканчивается память.
Вот код, который я использую:
WebClient request = new WebClient();
request.Credentials = new NetworkCredential(username, password);
byte[] fileData = request.DownloadData(baseURL + fName);
Как вы можете видеть... Я читаю файл непосредственно в памяти. Я уверен, что смогу это решить, если я прочитаю данные из HTTP в кусках и напишу их в файл на диске.
Как я могу это сделать?
Если вы используете WebClient.DownloadFile, вы можете сохранить его непосредственно в файл.
Класс WebClient является для упрощенных сценариев. После того, как вы пройдете мимо простых сценариев (и у вас есть), вам придется немного отступить и использовать WebRequest.
С помощью WebRequest у вас будет доступ к потоку ответов, и вы сможете зациклиться на нем, немного почитать и немного записать, пока не закончите.
Пример:
public void MyDownloadFile(Uri url, string outputFilePath)
{
const int BUFFER_SIZE = 16 * 1024;
using (var outputFileStream = File.Create(outputFilePath, BUFFER_SIZE))
{
var req = WebRequest.Create(url);
using (var response = req.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var buffer = new byte[BUFFER_SIZE];
int bytesRead;
do
{
bytesRead = responseStream.Read(buffer, 0, BUFFER_SIZE);
outputFileStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
}
}
}
Обратите внимание, что если WebClient.DownloadFile работает, я бы назвал это лучшим решением. Я написал выше, прежде чем был отправлен ответ "DownloadFile". Я также писал это слишком рано утром, поэтому может потребоваться зерно соли (и тестирование).
Вам нужно получить поток ответов, а затем прочитать в блоках, записывая каждый блок в файл, чтобы позволить повторно использовать память.
Как вы его написали, весь ответ, все 2GB, должен быть в памяти. Даже на 64-битной системе, которая достигнет предела 2 ГБ для одного объекта .NET.
Обновление: проще. Получите WebClient
, чтобы выполнить эту работу для вас: с помощью метода DownloadFile
, который поместит данные непосредственно в файл.
я бы использовал что-то вроде this
WebClient.OpenRead возвращает поток, просто используйте Read для циклического преобразования содержимого, поэтому данные не буферизуются в памяти, а могут быть записаны в виде блоков в файл.