skip to Main Content

I’m trying to download a ZIP file in ASP NET MVC. I have done in ASP NET Webforms, and it works correcly, but I do the same in MVC and I don’t get the same result, I tried the following:

public ActionResult Download()
{
    using (ZipFile zip = new ZipFile())
    {
        zip.AddDirectory(Server.MapPath("~/Directories/hello"));
        zip.Save(Server.MapPath("~/Directories/hello/sample.zip"));
        return File(Server.MapPath("~/Directories/hello/sample.zip"), 
                                   "application/zip", "sample.zip");
    }
}

But I get the binary data in screen, not the downloaded zip file why this is not working in MVC?
enter image description here

I have found that this does not work if I do it from a partial class, if I execute the download code from the Index and send the file if it works, why?

2

Answers


  1. I use this to download files. In your view:

    var ext = Path.GetExtension(path);
    string contentType = GetMimeType(ext);
    
    using (var stream = fileManager.GetStream(path))
    {
        var filename = fileManager.GetFileName(path);
        var response = System.Web.HttpContext.Current.Response;
        TransmitStream(stream, response, path, filename, contentType);
        return new EmptyResult();
    }
    

    Where GetMimeType is a method that return known MIME types:

    public static string GetMimeType(string extension, string defaultValue = "application/octet-stream")
    {
        if (extension == null)
        {
            throw new ArgumentNullException(nameof(extension));
        }
    
        if (!extension.StartsWith("."))
        {
            extension = "." + extension;
        }
    
        string mime;
        return _mappings.TryGetValue(extension, out mime) ? mime : defaultValue;
    }
    

    With _mappings as:

    private static readonly IDictionary<string, string> _mappings =
       new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) {
            {".323", "text/h323"},
            {".3g2", "video/3gpp2"},
            {".3gp", "video/3gpp"},
            {".3gp2", "video/3gpp2"},
            {".3gpp", "video/3gpp"},
            {".7z", "application/x-7z-compressed"},
    
            // Other types...
    
            {".xwd", "image/x-xwindowdump"},
            {".z", "application/x-compress"},
            {".zip", "application/x-zip-compressed"},
        };
    

    And the TransmitStream:

        public static void TransmitStream(
            Stream stream, HttpResponse response, string fullPath, string outFileName = null, string contentType = null)
        {
            contentType = contentType ?? MimeMapping.GetMimeMapping(fullPath);
    
            byte[] buffer = new byte[10000];
            try
            {
                var dataToRead = stream.Length;
    
                response.Clear();
                response.ContentType = contentType;
    
                if (outFileName != null)
                {
                    response.AddHeader("Content-Disposition", "attachment; filename=" + outFileName);
                }
    
                response.AddHeader("Content-Length", stream.Length.ToString());
    
                while (dataToRead > 0)
                {
                    // Verify that the client is connected.
                    if (response.IsClientConnected)
                    {
                        // Read the data in buffer.
                        var length = stream.Read(buffer, 0, 10000);
    
                        // Write the data to the current output stream.
                        response.OutputStream.Write(buffer, 0, length);
    
                        // Flush the data to the output.
                        response.Flush();
    
                        buffer = new byte[10000];
                        dataToRead = dataToRead - length;
                    }
                    else
                    {
                        // Prevent infinite loop if user disconnects
                        dataToRead = -1;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException(ex.Message);
            }
            finally
            {
                response.Close();
            }
        }
    
    Login or Signup to reply.
  2. Usually, if you want to download something i suggest you to use ContentResult
    ,transforming the file you want to download into a Base64 String and transforming it on the frontend using javascript with a Blob

    Action

    public ContentResult Download()
    {
       MemoryStream memoryStream = new MemoryStream();
       file.SaveAs(memoryStream);
    
       byte[] buffer = memoryStream.ToArray();
       string fileAsString = Convert.ToBase64String(buffer);
    
       return Content(file, "application/zip");
    }
    

    front end

    var blob = new Blob([Base64ToBytes(response)], { type: "application/zip" }); 
    var link = document.createElement("a");
    
    document.body.appendChild(link);
    
    link.setAttribute("type", "hidden");
    link.href = url.createObjectURL(blob);
    link.download = fileName;
    link.click();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search