Click here to Skip to main content
Click here to Skip to main content

How to Conditionally Return a Binary File from a Web API App and Save it to Disk at the Client

, 19 Feb 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Check for a newer version of a file and then return it if the client's version is outdated

What's New, ServerCat?!?

If you need a client app to check the Web API server to see if the server's version of a file is newer than the version the client has, you can set up the server to do so by performing these steps:

Add the appropriate method to a Repository Interface, such as:

HttpResponseMessage GetCervezaBeberUpdate(string clientVersion);

Add this to the corresponding Controller class (where the Controller name is "HenryFieldingController"):

[Route("api/HenryFielding/GetUpdatedCervezaBeber")]
public HttpResponseMessage GetUpdate(string clientVersion)
{
    return _tomJonesRepository.GetCervezaBeberUpdate(clientVersion);
}

Add the appropriate method to the concrete Repository class, such as:

public HttpResponseMessage GetCervezaBeberUpdate(string clientVersion)
{
    var binaryFilePath = HostingEnvironment.MapPath(@"~\App_Data\CervezaBeber.exe");
    FileVersionInfo currentVersion = FileVersionInfo.GetVersionInfo(binaryFilePath);
    if (!ServerFileIsNewer(clientVersion, currentVersion))
    {
        result = new HttpResponseMessage(HttpStatusCode.NoContent);
    }
    else
    {
        var stream = new FileStream(binaryFilePath, FileMode.Open);
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType =
            new MediaTypeHeaderValue("application/octet-stream");
    }
    return result;
}

Also add the method in that Repository class that GetCervezaBeberUpdate() calls:

private bool ServerFileIsNewer(string clientFileVersion, FileVersionInfo serverFile)
{
    Version client = new Version(clientFileVersion);
    Version server = new Version(string.Format("{0}.{1}.{2}.{3}", serverFile.FileMajorPart, serverFile.FileMinorPart, serverFile.FileBuildPart, serverFile.FilePrivatePart));
    return server > client;
}

Thanks to Servy, the method above is now as clean as an unblown whistle, as concise as Joe Friday's dream witness, and as elegant as Grace Kelley.

Whoa-oh-oh-oh-OH-oh!

Now the client can call this by passing a URI like this to the server:

http://<servername>:<portnumber>/api/
<controllername>?clientVersion=<clientversionquad>

Or, for a more literal example, in the event your server's name is "Platypus", the port to use is 4242, the Controller is named HenryFieldingController, and the version of the file the client currently has is 3.1.4.1:

http://Platypus:4242/api/HenryFielding?clientVersion=3.1.4.1

How About a Bonus?

As a free-as-in-beer (you/I wish!) premium, here's some code the client can use to save the server's response to a file (passing this a URI such as shown above):

private void DownloadTheFile(string uri)
{
    var outputFileName = "Platypus.exe";
    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
    var webResponse = (HttpWebResponse)webRequest.GetResponse();
    string statusCode = webResponse.StatusCode.ToString();
    // From here on (including the CopyStream() method) derived from Jon Skeet's 
    // answer at http://stackoverflow.com/questions/411592/how-do-i-save-a-stream-to-a-file
    if (statusCode == "NoContent")
    {
        MessageBox.Show("You already have the newest available version.");
    }
    else
    {
        var responseStream = webResponse.GetResponseStream();
        using (Stream file = File.Create(outputFileName))
        {
            CopyStream(responseStream, file);
            MessageBox.Show(string.Format("New version downloaded to {0}", outputFileName));
        }
    }
}

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8 * 1024];
    int len;
    while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, len);
    }
}

Oyez! Oyez!

If you like this tip and/or found it useful, you should either scale Mt. Rushmore and yell "How-dee!!!" like Minnie Pearl once you reach the summit, OR you should practice your falsetto until you can break a glass, a la Ella Fitzgerald. If you refuse to do either, you must simultaneously listen to Pearl Jam, "The Wreck of the Edmund Fitzgerald", and JFK's "Ask Not" speechifying.

OR!!! (I must be feeling magnanimous today) finish (no pun intended) this joke: "Sven the Finnish Carpenter was having lunch with Dane the Danish baker, when..."

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

B. Clay Shannon
Founder "Across Time & Space"
United States United States
Ideaman and Coder at Across Time & Space, creator of the Windows Store App "Photrax", which can be downloaded as a trial (7 days) from http://apps.microsoft.com/windows/en-us/app/photrax/75c18e6c-96bd-4607-ac43-531aab098ab4
 
Peripatetic and picaresque, I have lived in eight states; specifically, besides my native California (where I was born and where I now again reside) in chronological order: New York, Montana, Alaska, Oklahoma, Wisconsin, Idaho, and Missouri.
 
I am also a writer of both fiction (for which I use a nom de plume, "Blackbird Crow Raven", as a nod to my Native American heritage - I am "½ Cowboy, ½ Indian") and nonfiction: http://www.lulu.com/spotlight/blackbirdcraven
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411028.1 | Last Updated 19 Feb 2014
Article Copyright 2014 by B. Clay Shannon
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid