在MVC 4应用程序中下载文件流

时间:2015-10-27 04:20:46

标签: asp.net-mvc

我是MVC的新手,我正在尝试为网站创建一个下载页面,但遇到了问题。该页面包含许多可用文件,您可以在单击与其关联的按钮时下载该文件。

当收到下载请求时,将通过块中的套接字从远程服务器检索文件并将其写入响应流。当只有一个请求时,一切正常,但如果双击或其他用户同时发出请求,则会全部纠结。

问题是我如何对请求进行排队,以便在第二次和后续请求被执行之前完成一个下载请求。

感谢任何想法或帮助。

这是下载行动

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Download(string itemID)
    {
        System.Diagnostics.Debug.WriteLine("DOWNLOAD REQUEST");

        var downloadReq = new DownloadInfo() { ID = Convert.ToInt64(itemID), CurrentBlockNum = -1 };
        var username = User.Identity.Name;
        var request = new IDeskPacket(PacketType.Download, username, downloadReq);

        //get the first block of data
        var ideskResponse = (IDeskPacket)await RequestChannel.Instance.SendAync(request);
        if (ValidResponse(ideskResponse))
        {
            //initialise data
            var downloadInfo = (DownloadInfo)ideskResponse.Data;
            bool flush = false;

            //build the response stream
            Response.Clear();
            if (!Response.IsClientConnected)
            {
                System.Diagnostics.Debug.WriteLine("DOWNLOAD REQUEST FINISHED - DISCONNECTED");
                Response.End();
                return View("Error");
            }
            Response.ContentType = "application/octet-stream";
            Response.AddHeader("Content-Disposition", "attachment; filename=" + GetshortFilename(downloadInfo.Filename));
            Response.AddHeader("Content-Length", downloadInfo.FileSize.ToString());

            try
            {
                //loop until the end of the data or an invalid response
                do
                {
                    //write the received data to the response stream
                    Response.BinaryWrite(downloadInfo.DataBlock);

                    //null the data block out so it doesn't get sent back to the server later
                    downloadInfo.DataBlock = null;

                    //so we don't cache to much flush after every "other" data request
                    if (flush) Response.Flush();
                    flush = !flush;

                    //send request for next block of data
                    ideskResponse = (IDeskPacket)await RequestChannel.Instance.SendAync(ideskResponse);

                    //check the response and cache the data if valid
                    if (ValidResponse(ideskResponse)) downloadInfo = (DownloadInfo)ideskResponse.Data;

                } while (downloadInfo.CurrentBlockNum > 0);

            }
            catch (HttpException httpEx)
            {
                System.Diagnostics.Debug.WriteLine(httpEx.Message);
                //Response.Clear();
            }
            //signal the end of the response stream
            Response.End();

            System.Diagnostics.Debug.WriteLine("DOWNLOAD REQUEST FINISHED - FILE DOWNLOAD FINISHED");

            return View("Index", "UserDownload");
        }
        else
        {
            //redirect to error
            System.Diagnostics.Debug.WriteLine("DOWNLOAD REQUEST FINISHED - INVALID SERVER RESPONSE");
            return View("Error");
        }
    }

1 个答案:

答案 0 :(得分:0)

您可以使用Delegates构建队列和用户BeginInvoke,以便它可以异步处理您的请求,例如我为邮件发送构建了一个委托:

delegate bool MailSender(string to, string cc, string subject, string message);
public static void SendMailAsync(string to, string cc, string subject, string message)
    {
        MailSender sender = new MailSender(SendMail);
        AsyncCallback callback = new AsyncCallback(DisposeMail);
        sender.BeginInvoke(to, cc, subject, message, callback, "");
    }

private static void DisposeMail(IAsyncResult result)
    {
        AsyncResult delegateResult = (AsyncResult)result;
        MailSender delegateInstance = (MailSender)delegateResult.AsyncDelegate;
        delegateInstance.EndInvoke(result);
    }

Where&#34; SendMail&#34; ius是一个负责在你的情况下远程下载所需处理的函数,但这将被委托称为async。希望这有帮助