Web API 2 download file using async Task<IHttpActionResult>

Kcats Wolfrevo picture Kcats Wolfrevo · Feb 3, 2014 · Viewed 28.1k times · Source

I need to write a method like below to return a text document (.txt, pdf, .doc, .docx etc) While there are good examples of posting file in Web API 2.0 on the web , I couldn't find a relevant one for just downloading one. (I know how to do it in HttpResponseMessage.)

  public async Task<IHttpActionResult> GetFileAsync(int FileId)
  {    
       //just returning file part (no other logic needed)
  }

Does the above needs to be async at all? I am only looking to return stream. (Is that okay?)

More importantly before I end up doing the job one way or the otther, I wanted to know what's the "right" way of doing this sort of job... (so approaches and techniques mentioning this would be greatly appreciated).. thanks.

Answer

Kiran Challa picture Kiran Challa · Feb 6, 2014

Right, for your above scenario the action does not need to return an async action result. Here I am creating a custom IHttpActionResult. You can check my comments in the below code here.

public IHttpActionResult GetFileAsync(int fileId)
{
    // NOTE: If there was any other 'async' stuff here, then you would need to return
    // a Task<IHttpActionResult>, but for this simple case you need not.

    return new FileActionResult(fileId);
}

public class FileActionResult : IHttpActionResult
{
    public FileActionResult(int fileId)
    {
        this.FileId = fileId;
    }

    public int FileId { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage();
        response.Content = new StreamContent(File.OpenRead(@"<base path>" + FileId));
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

        // NOTE: Here I am just setting the result on the Task and not really doing any async stuff. 
        // But let's say you do stuff like contacting a File hosting service to get the file, then you would do 'async' stuff here.

        return Task.FromResult(response);
    }
}