0

my ActionResult provides a StreamContent file in the HttpResponseMessage result.Content. Now I would like to track the state of the download, to delete the file immediately after it was downloaded.

I found solutions that use the ByteStream, which split the file into chunks but that lacks the possibilities to provide a HttpStatusCode and other information in case some authorization tests deny the request.

This is my current controller:

    [HttpGet]
    public HttpResponseMessage GetZipDownload(string token, string guid)
    {

        if (!dOps.ValidateToken(token))
        {
            return Request.CreateResponse(HttpStatusCode.Unauthorized,
                new HttpError("Unauthorized"));
        }


        Device device = dOps.GetDeviceFromToken(auth);
        AssetOperations assetOps = new AssetOperations();

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

        FileStream file = assetOps.GetZip(guid);
        var content = new StreamContent(file);
        result.Content = content;
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
        result.Content.Headers.Add("Connection", "Keep-Alive");
        result.Content.Headers.Add("Content-Length", (file.Length).ToString());

        return result;
    }

Before I dig deeper into the ByteStream solution, I would like to ask if anybody probably knows about a reliable solution for ASP.NET MVC 5.

1
  • 1
    Although this isn't what you are asking for, just knowing that you sent all the data over the wire, doesn't guarantee you knowing that the client correctly received the file. To the best of my knowledge, HTTP can't help you with that, and even if it could, it still doesn't guarantee you that the client really processed and saved the file successfully, instead of crashing half way through. The general problem is called Two Generals' Problem - en.wikipedia.org/wiki/Two_Generals%27_Problem - and explains why the solution to your questions isn't as easy as you might think it is. Commented Mar 24, 2018 at 22:28

2 Answers 2

1

You can register EndRequest event handler to achieve it.

  1. Override Init() method inside MvcApplication class, and register to EndRequest event handler.
  2. Save into HttpContext.Current.Items the file path with a constant key.

Global.asax file

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // some startup code, removed for clearity
    }

    public override void Init()
    {
        base.Init();
        EndRequest += MvcApplication_EndRequest;
    }

    private void MvcApplication_EndRequest(object sender, EventArgs e)
    {
        if (
            HttpContext.Current.Request.Url.AbsolutePath == "/DownloadFileEndedWebsite/Home/Contact" // This should be adjusted.
            && HttpContext.Current.Items.Contains("DownloadFilePath"))
        {
            var filePath = HttpContext.Current.Items["DownloadFilePath"];
            // Delete file here..
        }
    }
}

HomeController.cs

public ActionResult Contact()
{
    HttpContext.Items.Add("DownloadFilePath", "DownloadFilePathValue");
    return View();
}
Sign up to request clarification or add additional context in comments.

Comments

0

You should create a method like: startDownload() from the UI thread. The idea of WebClient.DownloadFileAsync() is that it will spawn a worker thread for you automatically without blocking the calling thread.

As this thread explains, the Trhead will help you to have control of the download,

private void startDownload()
{
    Thread thread = new Thread(() => {
          WebClient client = new WebClient();
          client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
          client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
          client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
    });
    thread.Start();
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate {
          var bytesReceived = e.BytesReceived;
        //double bytesIn = double.Parse(e.BytesReceived.ToString());
        //double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
        //double percentage = bytesIn / totalBytes * 100;
        //label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
        //progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); // YOU CAN HAVE CONTROL OF THE PERCENTAGE OF THE DOWNLOAD, BUT, FOR MVC MAYBE IS BETTER NOT USE IT
    });
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate {
         //TODO: EXECUTE AN EVENT HERE, **THE DOWNLOAD ALREADY IS COMPLETED**!!!
    }); 
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.