Construir un ZIP en la memoria es útil cuando necesitas transmitir una descarga, pasar bytes a otro servicio, o almacenar un archivo en una base de datos sin tocar el disco. Aspose.ZIP para .NET expone una API limpia para crear archivos Z IP utilizando corrientes, elegir las configuraciones de compresión, y salvar el resultado a un MemoryStream o directamente a la respuesta HTTP.

Esta guía proporciona el código completo y correcto que puede insertar en una aplicación de consola o en un proyecto de ASP.NET Core.

Prerequisitos

  • .NET 6 o más tarde
  • El NuGet: Aspose.Zip
dotnet add package Aspose.Zip

Nombres utilizados:

using Aspose.Zip;                 // Archive, ArchiveEntry
using Aspose.Zip.Saving;          // DeflateCompressionSettings, CompressionLevel

Inicio rápido: crear un ZIP completamente en la memoria

Este ejemplo añade las entradas de una línea y un archivo en el disco, salva el arquivo a un MemoryStream, y expone el array de byte resultante.

// File: Program.cs
using System;
using System.IO;
using System.Text;
using Aspose.Zip;
using Aspose.Zip.Saving;

class Program
{
    static void Main()
    {
        // Prepare output buffer
        using var zipBuffer = new MemoryStream();

        // Choose compression (Deflate is the standard ZIP method)
        var deflate = new DeflateCompressionSettings(CompressionLevel.Normal);
        var entrySettings = new ArchiveEntrySettings(deflate);

        using (var archive = new Archive())
        {
            // 1) Add a text file from memory
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("Hello from Aspose.ZIP in memory.")))
            {
                archive.CreateEntry("docs/readme.txt", ms, entrySettings);
            }

            // 2) Add a file from disk (streamed; not fully loaded in RAM)
            var sourcePath = "report.pdf"; // ensure it exists
            if (File.Exists(sourcePath))
            {
                using var fs = File.OpenRead(sourcePath);
                archive.CreateEntry("reports/2025/report.pdf", fs, entrySettings);
            }

            // 3) Save the ZIP to our in-memory buffer
            archive.Save(zipBuffer);
        }

        // Use the ZIP bytes as needed (send over network, write to DB, etc.)
        byte[] zipBytes = zipBuffer.ToArray();
        Console.WriteLine($"ZIP size: {zipBytes.Length} bytes");
    }
}
  • Puntos clave *
  • new Archive() Crea un ZIP vacío.
  • CreateEntry(entryName, stream, entrySettings) añade un archivo de todos los flujos lecibles.
  • archive.Save(stream) escribe el archivo a su flujo elegido (memoria, red, cuerpo de respuesta).

Agregar un árbol entero sin escribir archivos temp

Caminar un directorio de forma recurrente, preservar los caminos relativos, y escribir el archivo final a la memoria.

using System.IO;
using Aspose.Zip;
using Aspose.Zip.Saving;

static class InMemoryZipper
{
    public static byte[] ZipFolderToBytes(string sourceFolder, CompressionLevel level = CompressionLevel.Normal)
    {
        if (!Directory.Exists(sourceFolder))
            throw new DirectoryNotFoundException(sourceFolder);

        var deflate = new DeflateCompressionSettings(level);
        var entrySettings = new ArchiveEntrySettings(deflate);

        using var buffer = new MemoryStream();
        using (var archive = new Archive())
        {
            var root = Path.GetFullPath(sourceFolder);
            foreach (var filePath in Directory.GetFiles(root, "*", SearchOption.AllDirectories))
            {
                var rel = Path.GetRelativePath(root, filePath).Replace(Path.DirectorySeparatorChar, '/');
                using var fs = File.OpenRead(filePath);
                archive.CreateEntry(rel, fs, entrySettings);
            }

            archive.Save(buffer);
        }
        return buffer.ToArray();
    }
}

ASP.NET Core: transmite una descarga ZIP sin disco I/O

Este punto final construye un ZIP en la memoria desde múltiples fuentes y lo devuelve con el tipo de contenido correcto y un nombre de archivo de descarga.

// File: Program.cs (minimal API)
using System.Text;
using Aspose.Zip;
using Aspose.Zip.Saving;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/download-zip", () =>
{
    using var buffer = new MemoryStream();
    var deflate = new DeflateCompressionSettings(CompressionLevel.Normal);
    var settings = new ArchiveEntrySettings(deflate);

    using (var archive = new Archive())
    {
        // Add dynamic content (for example, a CSV generated on the fly)
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("id,name\n1,Alice\n2,Bob\n")))
            archive.CreateEntry("data/users.csv", ms, settings);

        // Add a static file from disk if available
        var logo = "wwwroot/logo.png";
        if (File.Exists(logo))
        {
            using var fs = File.OpenRead(logo);
            archive.CreateEntry("assets/logo.png", fs, settings);
        }

        archive.Save(buffer);
    }

    buffer.Position = 0; // rewind for reading
    return Results.File(
        fileContents: buffer.ToArray(),
        contentType: "application/zip",
        fileDownloadName: $"bundle-{DateTime.UtcNow:yyyyMMdd-HHmmss}.zip");
});

app.Run();

*¿Por qué se hace esto aquí? *APIs mínimos requieren una carga de pago concreta.Para archivos muy grandes, prefiere streaming directamente a HttpResponse.Body:

app.MapGet("/stream-zip", async (HttpContext ctx) =>
{
    ctx.Response.ContentType = "application/zip";
    ctx.Response.Headers.ContentDisposition = $"attachment; filename=\"bundle.zip\"";

    var deflate = new DeflateCompressionSettings(CompressionLevel.Normal);
    var settings = new ArchiveEntrySettings(deflate);

    using var archive = new Archive();

    // Add entries...
    using var ms = new MemoryStream(Encoding.UTF8.GetBytes("hello"));
    archive.CreateEntry("hello.txt", ms, settings);

    // Stream directly to the client without buffering full ZIP in RAM
    await archive.SaveAsync(ctx.Response.Body);
});

Elegir las configuraciones de compresión

DeflateCompressionSettings Control de velocidad vs tamaño:

var fastest = new DeflateCompressionSettings(CompressionLevel.Low);      // fastest, larger files
var balanced = new DeflateCompressionSettings(CompressionLevel.Normal);  // default balance
var smallest = new DeflateCompressionSettings(CompressionLevel.High);    // slowest, smallest files

Pasar las configuraciones a través de new ArchiveEntrySettings(deflate) Cuando se crean las entradas, puede mezclar las configuraciones por entrada si es necesario.

Agregar entradas de los flujos de forma segura

  • Uso File.OpenRead(path) para transmitir grandes archivos sin cargarlos completamente en la memoria.
  • Para el contenido generado, escriba a MemoryStream o a PipeWriter-Suportar el flujo y pasarlo a CreateEntry.
  • Dispone de flujos después de cada CreateEntry de los recursos libres rápidamente.

Exemplos de contenido generado:

using System.IO;
using Aspose.Zip;
using Aspose.Zip.Saving;

static void AddLargeGeneratedEntry(Archive archive, string name)
{
    // simulate a big stream produced incrementally
    using var temp = new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite, FileShare.None, 81920, FileOptions.DeleteOnClose);
    using var writer = new StreamWriter(temp);
    for (int i = 0; i < 200_000; i++) writer.WriteLine($"row-{i},value-{i}");
    writer.Flush();
    temp.Position = 0;

    var settings = new ArchiveEntrySettings(new DeflateCompressionSettings(CompressionLevel.Normal));
    archive.CreateEntry(name, temp, settings);
}

Validación y tratamiento de errores

  • Verifique las entradas existentes antes de agregar a los archivos.
  • Creación en try/catch y devolver un claro error HTTP para las APIs web.
  • Paseos de entrada normalizados con avances adicionales (/para un comportamiento consistente en todas las herramientas.

Checklist de rendimiento

  • Choose CompressionLevel.Low para descargas en tiempo real cuando la velocidad es más importante que el tamaño.
  • Evite cargar entradas masivas completamente en la RAM; flujo de archivos o flujos de red.
  • Para archivos multi-GB muy grandes, fluye directamente a HttpResponse.Body o otro flujo objetivo en lugar de buffering.
  • Dispose Archive Todas las entradas fluyen de manera determinista.

FAQ

**¿Puedo proteger la contraseña del ZIP en memoria?**Aspose.ZIP soporta archivos ZIP cifrados. TraditionalEncryptionSettings o AesEncryptionSettings A través ArchiveEntrySettingsSolicitar por entrada al llamar CreateEntry.

**¿Puedo actualizar un ZIP existente que he cargado en la memoria?**Sí, cargue en una Archive, añadir o eliminar las entradas, luego Save Volver a una corriente.

**¿Esto funciona en el servicio de aplicaciones de Azure o en los contenedores?**Sí. En memoria y en streaming, el zipping funciona bien en entornos sandboxed donde el acceso al disco es limitado.

Resumen

Usted creó un archivo ZIP todo en memoria con Aspose.ZIP para .NET, añadió entradas de corrientes, se ajustó la composición, y devolvió el arquivo desde un punto final ASP.NET Core sin archivos temporales.

More in this category