Сохранить HTML с ресурсами в C#

Чтобы сохранить HTML с ресурсами в C#, загрузите HTMLDocument, при необходимости настройте HTMLSaveOptions.ResourceHandlingOptions и вызовите Save() с путем или ResourceHandler. Используйте FileSystemResourceHandler, пользовательский ZIP-обработчик или обработчик памяти, когда нужно управлять связанными CSS, изображениями, скриптами или выходными потоками.

HTML-документы часто зависят от связанных ресурсов: CSS-файлов, изображений, скриптов, шрифтов или страниц, на которые ссылается документ. Сохранения только основного .html файла может быть достаточно для сгенерированной разметки, но этого недостаточно, если сохраненный документ должен оставаться пригодным к использованию вне исходного расположения.

Aspose.HTML for .NET предоставляет API SaveOptions, ResourceHandlingOptions и ResourceHandler, чтобы управлять обработкой связанных ресурсов и местом хранения выходных потоков.

Используйте эту статью, когда нужно сохранить HTML-документ вместе с ресурсами, записать результат в пользовательскую папку, создать ZIP-архив или держать сохраненные ресурсы в памяти.

ResourceHandlingOptions для сохранения HTML

Класс SaveOptions – базовый класс, который позволяет задавать дополнительные параметры операций сохранения. Его свойство ResourceHandlingOptions настраивает обработку связанных ресурсов при сохранении.

ОпцияДля чего использовать
UrlRestrictionПрименяет ограничения к хостам или папкам, где расположены ресурсы.
MaxHandlingDepthУправляет глубиной связанных HTML-страниц, которые нужно обработать, если сценарий сохранения следует по ссылкам документа.
JavaScriptЗадает способ обработки JavaScript-файлов. Поддерживаются сохранение отдельно, встраивание в HTML, игнорирование или исключение скриптов. Значение по умолчанию – Save.
DefaultЗадает поведение для ресурсов, отличных от JavaScript. Поддерживаются значения Save, Ignore и Embed. Значение по умолчанию – Save.

Следующий пример C# создает save-with-linked-file.html, добавляет ссылку на linked.html и использует HTMLSaveOptions с ResourceHandlingOptions, чтобы управлять сохранением связанного HTML-файла.

Чтобы сохранить HTML-документ со связанными HTML-файлами в C#:

  1. Загрузите или создайте HTMLDocument, содержащий связанные ресурсы.
  2. Создайте экземпляр HTMLSaveOptions.
  3. Установите options.ResourceHandlingOptions.MaxHandlingDepth = 1, чтобы связанный HTML-файл мог быть обработан при сохранении.
  4. Вызовите document.Save(path, options), чтобы сохранить документ с настроенной обработкой ресурсов.
 1// Save HTML with a linked resources using C#
 2
 3// Prepare an output path for an HTML document 
 4string documentPath = Path.Combine(OutputDir, "save-with-linked-file.html");
 5
 6// Prepare a simple HTML file with a linked document
 7File.WriteAllText(documentPath, "<p>Hello, World!</p>" +
 8                                "<a href='linked.html'>linked file</a>");
 9
10// Prepare a simple linked HTML file
11File.WriteAllText(Path.Combine(OutputDir, "linked.html"), "<p>Hello, linked file!</p>");
12
13// Load the "save-with-linked-file.html" into memory
14using (HTMLDocument document = new HTMLDocument(documentPath))
15{
16    // Create a save options instance
17    HTMLSaveOptions options = new HTMLSaveOptions();
18
19    // The following line with value '0' cuts off all other linked HTML-files while saving this instance
20    // If you remove this line or change value to the '1', the 'linked.html' file will be saved as well to the output folder
21    options.ResourceHandlingOptions.MaxHandlingDepth = 1;
22
23    // Save the document with the save options
24    document.Save(Path.Combine(OutputDir, "save-with-linked-file_out.html"), options);
25}

Сохранить HTML в локальное файловое хранилище

HTML-документ может содержать разные ресурсы, например CSS, внешние изображения и другие связанные файлы. Aspose.HTML for .NET позволяет сохранять HTML со всеми связанными файлами с помощью ResourceHandler. Этот класс отвечает за обработку ресурсов и предоставляет методы, которые позволяют управлять действиями для каждого ресурса.

Рассмотрим пример сохранения HTML с ресурсами в локальное файловое хранилище, заданное пользователем. Исходный документ with-resources.html и связанный файл изображения находятся в одном каталоге. Конструктор FileSystemResourceHandler(customOutDir) принимает путь, куда будет сохранен документ с ресурсами, и создает объект FileSystemResourceHandler. Метод Save(resourceHandler) принимает этот объект и сохраняет HTML в выходное хранилище.

Чтобы сохранить HTML с ресурсами в локальную папку на C#:

  1. Загрузите HTML-документ, который ссылается на внешние ресурсы.
  2. Создайте FileSystemResourceHandler с целевым выходным каталогом.
  3. Вызовите document.Save(resourceHandler).
  4. Проверьте выходной каталог, где сохранены HTML-файл и связанные ресурсы.
 1// Save HTML with resources to local storage using C#
 2
 3// Prepare a path to a source HTML file
 4string inputPath = Path.Combine(DataDir, "with-resources.html");
 5
 6// Prepare a full path to an output directory 
 7string customOutDir = Path.Combine(Directory.GetCurrentDirectory(), "./../../../../tests-out/saving/");
 8
 9// Load the HTML document from a file
10using (HTMLDocument doc = new HTMLDocument(inputPath))
11{
12    // Save HTML with resources
13    doc.Save(new FileSystemResourceHandler(customOutDir));
14}

Сохранить HTML с ресурсами в ZIP-архив

Класс ResourceHandler можно реализовать, создав ZipResourceHandler. Это позволяет сформировать структурированный и сжатый архив, содержащий HTML-документ и связанные ресурсы, что удобно для архивирования, передачи или оптимизации хранения.

Метод HandleResource() в классе ZipResourceHandler настраивает обработку и сохранение отдельных ресурсов в ZIP-архиве.

В следующем примере класс ZipResourceHandler используется, чтобы сохранить документ with-resources.html вместе со связанными ресурсами в ZIP-архив.

Чтобы сохранить HTML с ресурсами в ZIP на C#:

  1. Загрузите HTML-документ со связанными ресурсами.
  2. Создайте пользовательский ZipResourceHandler для целевого пути архива.
  3. Передайте обработчик в document.Save(resourceHandler).
  4. Реализуйте HandleResource(), чтобы каждый ресурс документа записывался в архив.
 1// Save an HTML document with all linked resources into a ZIP archive using C#
 2
 3// Prepare a path to a source HTML file 
 4string inputPath = Path.Combine(DataDir, "with-resources.html");
 5
 6string dir = Directory.GetCurrentDirectory();
 7
 8// Prepare a full path to an output zip storage
 9string customArchivePath = Path.Combine(dir, "./../../../../tests-out/saving/archive.zip");
10
11// Load the HTML document 
12using (HTMLDocument doc = new HTMLDocument(inputPath))
13{
14    // Initialize an instance of the ZipResourceHandler class
15    using (ZipResourceHandler resourceHandler = new ZipResourceHandler(customArchivePath))
16    {
17        // Save HTML with resources to a Zip archive
18        doc.Save(resourceHandler);
19    }
20}

Класс ResourceHandler предназначен для пользовательской реализации. Класс ZipResourceHandler расширяет базовый ResourceHandler и предоставляет удобный способ управлять всем процессом обработки и сохранения ресурсов, связанных с HTML-документом, в ZIP-архив.

 1// Custom resource handler to save HTML with resources into a ZIP archive
 2
 3internal class ZipResourceHandler : ResourceHandler, IDisposable
 4{
 5    private FileStream zipStream;
 6    private ZipArchive archive;
 7    private int streamsCounter;
 8    private bool initialized;
 9
10    public ZipResourceHandler(string name)
11    {
12        DisposeArchive();
13        zipStream = new FileStream(name, FileMode.Create);
14        archive = new ZipArchive(zipStream, ZipArchiveMode.Update);
15        initialized = false;
16    }
17
18    public override void HandleResource(Resource resource, ResourceHandlingContext context)
19    {
20        string zipUri = (streamsCounter++ == 0
21            ? Path.GetFileName(resource.OriginalUrl.Href)
22            : Path.Combine(Path.GetFileName(Path.GetDirectoryName(resource.OriginalUrl.Href)),
23                Path.GetFileName(resource.OriginalUrl.Href)));
24        string samplePrefix = String.Empty;
25        if (initialized)
26            samplePrefix = "my_";
27        else
28            initialized = true;
29
30        using (Stream newStream = archive.CreateEntry(samplePrefix + zipUri).Open())
31        {
32            resource.WithOutputUrl(new Url("file:///" + samplePrefix + zipUri)).Save(newStream, context);
33        }
34    }
35
36    private void DisposeArchive()
37    {
38        if (archive != null)
39        {
40            archive.Dispose();
41            archive = null;
42        }
43
44        if (zipStream != null)
45        {
46            zipStream.Dispose();
47            zipStream = null;
48        }
49
50        streamsCounter = 0;
51    }
52
53    public void Dispose()
54    {
55        DisposeArchive();
56    }
57}

Сохранить HTML с ресурсами в потоки памяти

Пользовательская реализация ResourceHandler также может сохранять HTML и связанные ресурсы в потоки памяти. Это удобно в серверных сценариях, где результат нужно передать в другой сервис, сохранить в базе данных, вернуть из API или обработать без промежуточной записи файлов на диск.

Следующий код показывает, как использовать класс MemoryResourceHandler, чтобы сохранить HTML-документ в памяти, собрать обработанные ресурсы и вывести информацию о них.

Чтобы сохранить HTML с ресурсами в потоки памяти на C#:

  1. Инициализируйте HTMLDocument, используя указанный путь к HTML-файлу.
  2. Создайте экземпляр класса MemoryResourceHandler.
  3. Вызовите document.Save(resourceHandler) и передайте экземпляр обработчика памяти.
  4. Используйте метод PrintInfo() класса MemoryResourceHandler, чтобы вывести информацию об обработанных ресурсах.
 1// Save HTML with resources to memory streams using C#
 2
 3// Prepare a path to a source HTML file 
 4string inputPath = Path.Combine(DataDir, "with-resources.html");
 5
 6// Load the HTML document 
 7using (HTMLDocument doc = new HTMLDocument(inputPath))
 8{
 9    // Create an instance of the MemoryResourceHandler class and save HTML to memory
10    MemoryResourceHandler resourceHandler = new MemoryResourceHandler();
11    doc.Save(resourceHandler);
12    resourceHandler.PrintInfo();
13}

После выполнения примера выводится сообщение о хранении в памяти:

uri:memory:///with-resources.html, length:256
uri:memory:///photo1.png, length:57438

Класс ResourceHandler – базовый класс для создания и управления выходными потоками. Класс MemoryResourceHandler позволяет захватывать и хранить ресурсы в потоках памяти, предоставляя гибкий способ обработки ресурсов без физического сохранения в файловой системе.

 1// In-memory resource handler that captures and stores HTML resources as streams
 2
 3internal class MemoryResourceHandler : ResourceHandler
 4{
 5    public List<Tuple<Stream, Resource>> Streams;
 6
 7    public MemoryResourceHandler()
 8    {
 9        Streams = new List<Tuple<Stream, Resource>>();
10    }
11
12    public override void HandleResource(Resource resource, ResourceHandlingContext context)
13    {
14        MemoryStream outputStream = new MemoryStream();
15        Streams.Add(Tuple.Create<Stream, Resource>(outputStream, resource));
16        resource
17            .WithOutputUrl(new Url(Path.GetFileName(resource.OriginalUrl.Pathname), "memory:///"))
18            .Save(outputStream, context);
19    }
20
21    public void PrintInfo()
22    {
23        foreach (Tuple<Stream, Resource> stream in Streams)
24            Console.WriteLine($"uri:{stream.Item2.OutputUrl}, length:{stream.Item1.Length}");
25    }
26}

Как выбрать сценарий сохранения ресурсов

ЦельРекомендуемый сценарий
Сохранить основной HTML-документ и связанные ресурсы как файлыИспользуйте HTMLSaveOptions и ResourceHandlingOptions, либо FileSystemResourceHandler, когда нужен пользовательский выходной каталог.
Сохранить HTML и ресурсы в пользовательскую папкуИспользуйте FileSystemResourceHandler(customOutDir) и передайте его в document.Save(resourceHandler).
Упаковать HTML и ресурсы для архива или передачиРеализуйте ZipResourceHandler и записывайте ресурсы в ZIP-архив из HandleResource().
Держать выходные данные в памятиРеализуйте MemoryResourceHandler и храните потоки ресурсов в памяти для дальнейшей обработки.
Управлять обработкой JavaScriptНастройте ResourceHandlingOptions.JavaScript; значение по умолчанию – Save.

Типичные проблемы при сохранении ресурсов

ПроблемаПричинаРешение
CSS или изображения отсутствуют в выводеСвязанные ресурсы не были сохранены или ограничения URL не позволили их обработать.Проверьте ResourceHandlingOptions и используйте сценарий с ResourceHandler, если нужно контролировать хранилище вывода.
Ресурсы сохраняются не туда, куда ожидалосьПуть сохранения по умолчанию или путь обработчика не совпадает с ожидаемой структурой хранилища.Используйте FileSystemResourceHandler(customOutDir), когда выходной каталог должен быть задан явно.
В ZIP-архиве не хватает файловHandleResource() не записывает каждый обработанный ресурс в архив.Проверьте реализацию пользовательского ZipResourceHandler и обрабатывайте каждый ресурс, переданный в HandleResource().
При сохранении растет потребление памятиКрупные ресурсы удерживаются в потоках памяти.Используйте файловый вывод или потоковую обработку для больших ресурсов, либо освобождайте потоки сразу после передачи в следующий этап обработки.
JavaScript-файлы не встроеныДля JavaScript используется поведение Save по умолчанию.Установите ResourceHandlingOptions.JavaScript в режим встраивания, если требуются встроенные скрипты.

FAQ

Как сохранить HTML с CSS и изображениями в C#?

Загрузите HTML-документ, настройте HTMLSaveOptions или используйте ResourceHandler, затем вызовите Save(), чтобы связанные ресурсы были обработаны вместе с документом.

Когда использовать FileSystemResourceHandler?

Используйте FileSystemResourceHandler, когда нужно сохранить HTML-документ и связанные ресурсы в конкретный локальный выходной каталог.

Можно ли сохранить HTML и ресурсы в ZIP-архив?

Да. Реализуйте пользовательский ZipResourceHandler и записывайте каждый обработанный ресурс в архив внутри HandleResource().

Можно ли сохранить ресурсы без записи файлов на диск?

Да. Реализуйте ResourceHandler на базе памяти и храните обработанные ресурсы в потоках памяти для дальнейшей обработки.

Связанные статьи

Полные примеры C# и файлы данных доступны в репозитории Aspose.HTML for .NET на GitHub.