Click here to Skip to main content
15,889,877 members
Articles / Web Development / ASP.NET
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
4.80/5 (5 votes)
19 Feb 2014CPOL2 min read 21.5K   10  
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:

C#
HttpResponseMessage GetCervezaBeberUpdate(string clientVersion);

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

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

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

C#
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:

C#
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):

C#
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)


Written By
Founder Across Time & Space
United States United States
I am in the process of morphing from a software developer into a portrayer of Mark Twain. My monologue (or one-man play, entitled "The Adventures of Mark Twain: As Told By Himself" and set in 1896) features Twain giving an overview of his life up till then. The performance includes the relating of interesting experiences and humorous anecdotes from Twain's boyhood and youth, his time as a riverboat pilot, his wild and woolly adventures in the Territory of Nevada and California, and experiences as a writer and world traveler, including recollections of meetings with many of the famous and powerful of the 19th century - royalty, business magnates, fellow authors, as well as intimate glimpses into his home life (his parents, siblings, wife, and children).

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, including a two-volume social and cultural history of the U.S. which covers important events from 1620-2006: http://www.lulu.com/spotlight/blackbirdcraven

Comments and Discussions

 
-- There are no messages in this forum --