Zip'ануть картинки налету из стрима, не сохраняя файл на диск
Задача поставлена так: Нужно извлечь все картинки из html-страницы и сжать их Zip'ом не сохраняя при этом на диск. Реализовать на C#.
Собственно картинки я скачиваю и даже на лету сжимаю зипом не скидывая их на диск пода проблема в том что из например 3 картинок всегда остается последняя третья. Будто они затираются каждый раз. А мне нужно чтобы все 3 были в архиве.
Вот пример кода который с набросал.
public byte[] GetImage(String urlTo)
{
MemoryStream compressedFileStream = new MemoryStream();
WebClient client = new WebClient();
String source = client.DownloadString(urlTo);
HtmlDocument document = new HtmlDocument();
document.LoadHtml(source);
foreach (var link in document.DocumentNode.Descendants("img")
.Select(i => i.Attributes["src"]))
{
String ext = Path.GetExtension(link.Value);
if (ext == ".jpeg")
{
Console.WriteLine(link.Value);
byte[] data = client.DownloadData(link.Value);
using (compressedFileStream = new MemoryStream())
{
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false))
{
string name = link.Value.Split('/').Last();
var zipEntry = zipArchive.CreateEntry(name);
using (var originalFileStream = new MemoryStream(data))
using (var zipEntryStream = zipEntry.Open())
{
originalFileStream.CopyTo(zipEntryStream);
}
}
}
}
}
return compressedFileStream.ToArray();
}
Ответы (1 шт):
На каждой итерации цикла foreach вы пересоздаёте zipArchive. Поэтому нужно перенести цикл внутрь.
К тому же я бы посоветовал отказаться от устаревшего класса WebClient и применить HttpClient. При этом лучше использовать асинхронные методы.
В итоге код может выглядеть примерно так:
public async Task<byte[]> GetImageAsync(string urlTo)
{
using (var client = new HttpClient())
{
string source = await client.GetStringAsync(urlTo);
var document = new HtmlDocument();
document.LoadHtml(source);
using (var compressedFileStream = new MemoryStream())
{
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false))
{
foreach (var link in document.DocumentNode.Descendants("img")
.Select(i => i.Attributes["src"]))
{
string ext = Path.GetExtension(link.Value);
if (ext == ".jpeg")
{
Console.WriteLine(link.Value);
string name = link.Value.Split('/').Last();
var zipEntry = zipArchive.CreateEntry(name);
using (var stream = await client.GetStreamAsync(link.Value))
using (var zipEntryStream = zipEntry.Open())
{
await stream.CopyToAsync(zipEntryStream);
}
}
}
}
return compressedFileStream.ToArray();
}
}
}
Ещё лучше иметь всего один экземпляр HttpClient на приложение. Поэтому следует вынести его из метода и сделать, например, статическим полем.