0

I am trying to download a CSV template that only contains one extremely long comma-separated string. My API endpoint is exactly like so:

public HttpResponse DownloadTemplate()
{
    var attachment = "attachment; filename=template.csv";
    var headers = "Header1,Header2,Header3,HeaderAndSoOnAndSoForth";

    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.ClearHeaders();
    HttpContext.Current.Response.ClearContent();
    HttpContext.Current.Response.AddHeader("Content-Disposition", attachment);
    HttpContext.Current.Response.ContentType = "text/csv";
    HttpContext.Current.Response.AddHeader("Pragma", "public");
    HttpContext.Current.Response.Write(headers);

    return HttpContext.Current.Response;
}

This is invoked by a simple AngularJS $http.post request:

$http.post('api/Files/DownloadTemplate').success(function (data) {
    // Do something with data.
});

However, when I'm checking the network response and nothing seems to be returned at all. What am I doing wrong?

(A friend suggested storing the file in the server and just downloading it. Due to a multitude of reasons, I am not allowed to do this.)

WGS
  • 13,969
  • 4
  • 48
  • 51
  • 1
    For the "reason"/why - [you can't trigger download via XHR](http://stackoverflow.com/a/20830337/304683), which is what `Content-Disposition", attachment` is..Hth... – EdSF Mar 18 '16 at 04:57

1 Answers1

1

I'm kinda wondering why you are not just returning the string, since you are processing the data immediately in your $http.post. So maybe this answer isn't applicable, but I'll post it anyway since it took me a while to figure out and if it's relevant then great.

But, if we are talking true file download, I've implemented it in Angular, calling into my WebAPI, using the following technique:

public HttpResponseMessage DownloadFile()
{
    var content = DoSomeProcessingToGetContentAsByteArray();

    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        // Haven't checked, but there may be a StringContent() instead?
        Content = new ByteArrayContent(content)
    };

    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
    {
        FileName = "template.csv"
    };

    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    return result;
}

Then from Angular:

window.open("http://whatever/api/Files/DownloadTemplate", "_blank", "");

Will prompt the user to save the file.

Brendan Green
  • 11,676
  • 5
  • 44
  • 76
  • Let me check this and get back to you. Currently on the move so I can't fully test it yet. – WGS Mar 18 '16 at 01:32