【问题标题】:Asynchronous streaming of large files using ASP.Net Framework 2.0使用 ASP.Net Framework 2.0 对大文件进行异步流式传输
【发布时间】:2017-05-27 09:26:12
【问题描述】:

我正在开发一个 ASP.NET 框架 2.0 应用程序。在特定页面上,我提供了一个用户链接。通过单击此链接,将打开一个带有另一个 aspx 页面的窗口。该页面实际上向指向文件的第三方 url 发送 http 请求(例如 - 从云下载文件的镜像 url)。 http 响应在用户点击链接的第一页使用 response.write 发送回用户。

现在,我面临的问题是如果文件大小很小,那么它可以正常工作。但是,如果文件很大(即超过 1 GB),那么我的应用程序会等到从 URL 下载整个文件。我尝试使用 response.flush() 逐块向用户发送数据,但用户仍然无法使用应用程序,因为工作进程正忙于从第三方 URL 获取数据流。

有什么方法可以异步下载大文件,以便我的弹出窗口完成其执行(下载正在进行中),并且用户可以在应用程序上并行执行其他活动。

谢谢, 苏沃迪普

【问题讨论】:

    标签: c# asp.net httpwebrequest httpresponse httpwebresponse


    【解决方案1】:

    使用 WebClient 读取远程文件。您可以从 WebClient 获取流,而不是下载。将其放入 while() 循环并将来自 WebClient 流的字节推送到响应流中。这样,您将同时异步下载和上传。

    HttpRequest 示例:

    private void WriteFileInDownloadDirectly()
    {
        //Create a stream for the file
        Stream stream = null;
    
        //This controls how many bytes to read at a time and send to the client
        int bytesToRead = 10000;
    
        // Buffer to read bytes in chunk size specified above
        byte[] buffer = new byte[bytesToRead];
    
        // The number of bytes read
        try
        {
            //Create a WebRequest to get the file
            HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create("Remote File URL");
    
            //Create a response for this request
            HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
    
            if (fileReq.ContentLength > 0)
                fileResp.ContentLength = fileReq.ContentLength;
    
            //Get the Stream returned from the response
            stream = fileResp.GetResponseStream();
    
            // prepare the response to the client. resp is the client Response
            var resp = HttpContext.Current.Response;
    
            //Indicate the type of data being sent
            resp.ContentType = "application/octet-stream";
    
            //Name the file 
            resp.AddHeader("Content-Disposition", $"attachment; filename=\"{ Path.GetFileName("Local File Path - can be fake") }\"");
            resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
    
            int length;
            do
            {
                // Verify that the client is connected.
                if (resp.IsClientConnected)
                {
                    // Read data into the buffer.
                    length = stream.Read(buffer, 0, bytesToRead);
    
                    // and write it out to the response's output stream
                    resp.OutputStream.Write(buffer, 0, length);
    
                    // Flush the data
                    resp.Flush();
    
                    //Clear the buffer
                    buffer = new byte[bytesToRead];
                }
                else
                {
                    // cancel the download if client has disconnected
                    length = -1;
                }
            } while (length > 0); //Repeat until no data is read
        }
        finally
        {
            if (stream != null)
            {
                //Close the input stream
                stream.Close();
            }
        }
    }
    

    WebClient 流读取:

    using (WebClient client = new WebClient())
    {
         Stream largeFileStream = client.OpenRead("My Address");
    }
    

    【讨论】:

    • Ваньо,上面的 HttpWebRequest 示例与我当前的实现完全相同。我提供了一个 http url 来创建 httpwebrequest。但问题是它不断循环通过while循环,直到1 GB文件结束,然后主进程退出while循环以结束进程。
    • 我如何异步使用 Webclient 以便可以并行下载文件。请提出建议。
    • 更新了我的答案。这就是您可以从 WebClient 获取流的方式。那么逻辑是一样的——while循环和读取块。
    猜你喜欢
    • 2019-07-03
    • 2017-10-10
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 2018-10-21
    相关资源
    最近更新 更多