Home > Blockchain >  ASP NET MVC download ZIP file
ASP NET MVC download ZIP file

Time:05-24

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?

CodePudding user response:

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();
        }
    }

CodePudding user response:

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();
  • Related