【问题标题】:c# mvc - Downloading huge files hangs web applicationc# mvc - 下载大文件会挂起 Web 应用程序
【发布时间】:2020-09-24 19:39:04
【问题描述】:

我有一项功能,允许用户通过单击网页上的文件名从服务器下载文件。我正在使用 ASP.Net MVC5。任何大小的下载(尝试最大 2GB)都适用于我当前的实现。问题是在下载大于 200MB 的文件时,Web 应用程序会挂起,直到完成下载。

当前实施: 当用户点击网格中的 fileName 时,它​​会触发 'DocumentController' 中的 'Download' ActionMethod,从而从服务器下载文件。

然后我想到了两种方法来解决上述问题:

Approach1:使用异步功能。我是异步编程的新手。如果这是最好的方法,你能否更新我下面的代码以表现异步。

 public ActionResult Download(string filePath, string fileName)
    {
        try
        {
            if(!string.IsNullOrEmpty(filePath))
            {
                filePath = Path.Combine(baseUrl, filePath);
                string contentType = MimeMapping.GetMimeMapping(fileName);

                TransmitFile(filePath, fileName);
            }
        }
        catch(Exception ex) { }
        return Content("");
    }

    private void TransmitFile(string fullPath, string outFileName)
    {
        System.IO.Stream iStream = null;

        // Buffer to read 10K bytes in chunk:
        byte[] buffer = new Byte[10000];

        // Length of the file:
        int length;

        // Total bytes to read:
        long dataToRead;

        // Identify the file to download including its path.
        string filepath = fullPath;

        // Identify the file name.
        string filename = System.IO.Path.GetFileName(filepath);

        try
        {
            // Open the file.
            iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
                        System.IO.FileAccess.Read, System.IO.FileShare.Read);


            // Total bytes to read:
            dataToRead = iStream.Length;

            Response.Clear();
            Response.ContentType = MimeMapping.GetMimeMapping(filename);
            Response.AddHeader("content-disposition", "attachment; filename=\"" + outFileName + "\"");
            Response.AddHeader("Content-Length", iStream.Length.ToString());

            // Read the bytes.
            while (dataToRead > 0)
            {
                // Verify that the client is connected.
                if (Response.IsClientConnected)
                {
                    // Read the data in buffer.
                    length = iStream.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
        {
            if (iStream != null)
            {
                //Close the file.
                iStream.Close();
            }
            Response.Close();
        }
    }

方法 2:Ajax 调用“下载”ActionMethod。这对我来说效果不佳。

function downloadFile() {    
var data = //Gets data object using some action and works fine

$.ajax({
    url: '/Document/IsFileExistOnServer',
    data: { 'filePath': data.path },
    type: 'GET',
    success: function (isFileExist) {
        if (typeof isFileExist != "undefined" && isFileExist != null) {
            if (isFileExist == "true") {
                window.location = '@Url.Action("Download", "Document", new { filePath =' + data.path + ', fileName =' + data.name + ' })';                    
            }
            else {
                alert("File Not found. Cannot download");
            }
        }
    },
    error: function (data) {
        alert("Error occured. Please try again.")
    }
});

}

ajax 调用的问题是,请求下载文件的视图与另一个控制器(HomeController)相关联,单击下载时,当前页面被重定向到如下链接: http://localhost:59740/Home/Details/@Url.Action(Download,Document,new {filePath=2017/05/TestFile.db,fileName=test1Gb.db})

请有人帮助我以最好的方式做到这一点。提前谢谢!!!

【问题讨论】:

  • 您的应用程序是否需要在代码中处理该下载,或者您是否可以提供指向http://localhost:59740/2017/05/TestFile.db 文件的“直接”链接?
  • 要求是在代码中处理下载。文件存储服务器与应用程序服务器不同,因此我认为,我不能使用这样的“直接”链接。
  • 您的 IT 人员能否为该文件服务器设置virtual directory
  • 我需要和他核实一下。如果他说是:我应该对我的代码进行哪些更改,如果他说否:没有其他方法可以做到这一点?
  • @MadMyche:您的想法并非不可能,但它增加了一个需要公共访问这些文件的显着限制。这是一个很大的假设,并且绝不会自动成为 OP 的情况。下载处理程序从 ASP.Net 早期就已经存在,没有理由反对这个完善的功能。

标签: c# ajax asp.net-mvc


【解决方案1】:

我认为你应该使用这个:

Response.OutputStream.WriteAsync(buffer, 0, length);

而不是这个:

Response.OutputStream.Write(buffer, 0, length);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    相关资源
    最近更新 更多