Saltar al contenido

Utilice MemoryStream y ZipArchive para devolver el archivo zip al cliente en la api web asp.net

Ya no tienes que buscar más en otras webs ya que has llegado al lugar indicado, poseemos la solución que quieres hallar pero sin problemas.

Solución:

$.ajax maneja las respuestas de texto e intentará (utf-8) decodificar el contenido: su archivo zip no es texto, obtendrá un contenido corrupto. jQuery no admite contenido binario, por lo que debe usar este enlace y agregar un transporte ajax en jQuery o usar directamente un XmlHttpRequest. Con un xhr, debe configurar xhr.responseType = "blob" y leer de xhr.response la gota.

// with xhr.responseType = "arraybuffer"
var arraybuffer = xhr.response;
var blob = new Blob([arraybuffer], type:"application/zip");
saveAs(blob, "example.zip");

// with xhr.responseType = "blob"
var blob = xhr.response;
saveAs(blob, "example.zip");
Edit: examples:

con jquery.binarytransport.js (cualquier biblioteca que le permita descargar un Blob o un ArrayBuffer servirá)

$.ajax(
  url: url,
  type: "POST",
  contentType: "application/json",
  dataType: "binary", // to use the binary transport
  // responseType:'blob', this is the default
  data: data,
  processData: false,
  success: function (blob) 
    // the result is a blob, we can trigger the download directly
    saveAs(blob, "example.zip");
  
  // [...]
);

con un XMLHttpRequest sin procesar, puede ver esta pregunta, solo necesita agregar un xhr.responseType = "blob" para obtener una mancha.

Personalmente te recomendé que usaras un transporte ajax en jQuery, eso es muy fácil, tienes que descargar una biblioteca, incluirla en el proyecto y escribir: dataType: "binary".

Este es el código API, usando DotNetZip (Ionic.Zip):

   [HttpPost]
    public HttpResponseMessage ZipDocs([FromBody] string[] docs)
    
        using (ZipFile zip = new ZipFile())
        
            //this code takes an array of documents' paths and Zip them
            zip.AddFiles(docs, false, "");
            return ZipContentResult(zip);
        
    

    protected HttpResponseMessage ZipContentResult(ZipFile zipFile)
    
        var pushStreamContent = new PushStreamContent((stream, content, context) =>
        
          zipFile.Save(stream);
            stream.Close(); 
        , "application/zip");

        return new HttpResponseMessage(HttpStatusCode.OK)  Content = pushStreamContent ;
    

Aquí está mi solución que funcionó para mí.

Lado C #

public IActionResult GetZip([FromBody] List documents)

    List listOfDocuments = new List();

    foreach (DocumentAndSourceDto doc in documents)
        listOfDocuments.Add(_documentService.GetDocumentWithServerPath(doc.Id));

    using (var ms = new MemoryStream())
    
        using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
        
            foreach (var attachment in listOfDocuments)
            
                var entry = zipArchive.CreateEntry(attachment.FileName);

                using (var fileStream = new FileStream(attachment.FilePath, FileMode.Open))
                using (var entryStream = entry.Open())
                
                    fileStream.CopyTo(entryStream);
                
            

        
        ms.Position = 0;
        return File(ms.ToArray(), "application/zip");
    

    throw new ErrorException("Can't zip files");

no te pierdas el ms.Position = 0; aquí

Lado delantero (Angular 4):

downloadZip(datas: any) 
    const headers = new Headers(
        'Content-Type': 'application/json',
        'Accept': 'application/zip'
    );

    const options = new RequestOptions( headers: headers, withCredentials: true, responseType: ResponseContentType.ArrayBuffer );
    const body = JSON.stringify(datas);
    return this.authHttp.post(`$environment.apiBaseUrlapi/documents/zip`, body, options)
        .map((response: Response) => 
            const blob = new Blob([response.blob()],  type: 'application/zip' );
            FileSaver.saveAs(blob, 'logs.zip');
        )
        .catch(this.handleError);

Ahora puedo descargar varios archivos en zip.

Esto es adecuado para la versión principal de asp.net.

    [HttpGet("api/DownloadZip")]
    public async Task Download()
    
        var path = "C:\test.zip";
        var memory = new MemoryStream();
        using (var stream = new FileStream(path, FileMode.Open))
        
            await stream.CopyToAsync(memory);
        

        memory.Position = 0;
        return File(memory, GetContentType(path), Path.GetFileName(path));
    

Luego use la llamada del cliente web

      class Program
    

        static string url = "http://localhost:5000/api/DownloadZip";

        static async Task Main(string[] args)
        
            var p = @"c:temp1test.zip";

            WebClient webClient = new WebClient();

            webClient.DownloadFile(new Uri(url), p);                       

            Console.WriteLine("ENTER to exit...");
            Console.ReadLine();
        
    

Comentarios y puntuaciones de la guía

Si te ha sido de utilidad nuestro artículo, sería de mucha ayuda si lo compartes con otros seniors de este modo contrubuyes a extender nuestra información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *