Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I download a file to a remote machine the same or similarly to how I'm doing it to my own machine?

I'm downloading an Excel file (dynamically created in a Winforms app and saved to a database) in a Web API project using this method:

[Route("api/deliveryperformance/{unit}/{begindate}/{enddate}")]
public HttpResponseMessage Get(string unit, string begindate, string enddate)
{
    // adapted the first part of this code from http://stackoverflow.com/questions/11176066/how-do-i-insert-retrieve-excel-files-to-varbinarymax-column-in-sql-server-2008
    byte[] excelContents;

    string selectStmt = "SELECT BinaryData FROM ReportsGenerated WHERE FileBaseName = @fileBaseName";
    string fbn = string.Format("deliveryperformance/{0}/{1}/{2}", unit, begindate, enddate);
    using (SqlConnection connection = new SqlConnection(ProActWebReportsConstsAndUtils.CPSConnStr))
    using (SqlCommand cmdSelect = new SqlCommand(selectStmt, connection))
    {
        cmdSelect.Parameters.Add("@fileBaseName", SqlDbType.VarChar).Value = fbn;

        connection.Open();
        excelContents = (byte[])cmdSelect.ExecuteScalar();
        connection.Close();
    }
    string excelFileName = "C:\\Misc\\TestFile2.xlsx";
    File.WriteAllBytes(excelFileName, excelContents);

    String HtmlToDisplay = GetDownloadSuccessMessage(excelFileName);
    return new HttpResponseMessage()
    {
        Content = new StringContent(
            HtmlToDisplay,
            Encoding.UTF8,
            "text/html"
        )
    };
}

internal static string GetDownloadSuccessMessage(string excelFileName)
{
    return string.Format("<h1>Excel spreadsheed downloaded to {0}</h1>", excelFileName);
}

This works just fine (except that there is no downloading action visible, such as the file's icon dropping to the taskbar, as is normally the case when downloading files from the Internet - the file simply winds up in the location indicated).

My assumption is that this only works because I am running the ASP.NET Web API project locally and so my file system is considered "fair game" for writing.

How can I accomplish the same thing (preferably with the visible downloading heretofore mentioned) on any remote user's machine (obviously, I can't just place the file anywhere, not only for security reasons, but also because I don't know which folders they might have)?

UPDATE

I was going to try this:

HttpResponseMessage httprm = new HttpResponseMessage();
httprm.Buffer = true;
httprm.Charset = "";
httprm.Cache.SetCacheability(HttpCacheability.NoCache);
httprm.ContentType = "application/vnd.ms-excel";
httprm.AddHeader("content-disposition", "attachment;filename=\"Funk49.xlsx\"");
httprm.BinaryWrite(bytes);
httprm.Flush();
httprm.End();

...adapted from here, but none of those properties or methods are part of HttpResponseMessage's milieau. I even tried a raw "Response.Buffer" in place of "httprm.Buffer", hoping the undeclared "Response" object (not declared in the sample code, either) would at least afford me resolvability, but no such serendipity shone on me.

UPDATE 2

I am going to bountify the accepted answer ASAP; it was one of the most helpful ones I've ever gotten. I combined that wisdom with other bits and pieces to compile (no pun intended) a tip that shows how to save Excel data and then read it out again from a Web API app and download it here.

like image 879
B. Clay Shannon-B. Crow Raven Avatar asked Mar 31 '16 22:03

B. Clay Shannon-B. Crow Raven


1 Answers

Well you seem not to be downloading anything as such, you just perform a write to the servers local C: drive.

To download you would return the excelContents buffer instead of your current HTML string, E.g.

HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(excelContents);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "blah.xlsx";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

return result;
like image 183
Alex K. Avatar answered Oct 05 '22 17:10

Alex K.