Flickr-ing about with .NET
| |
This blog details about the flickering in .net |
|
Sam Judson
Difficulty: Intermediate
Time Required: 1-3 hours
Cost: Free
Hardware:
|
Everyone who is anyone seems to be messing about with Flickr these days, one of the newest waves of "Web 2.0" Web-based applications. With its now much imitated style, social networking orientated layout, and use of the newest AJAX technologies to provide the user with a truly interactive experience, Flickr sets the bar for the future of applications on the Internet. Also one of the key benchmarks of a "Web 2.0" application (sorry, that’s the last time I'll use that word, honestly) is the public API that has been delivered and can be used by you and me to provide new and interesting ways of displaying and manipulating photos.
Getting Started
The first thing I will mention is that this article is aimed at .NET 2.0, but the Flickr.Net API library works just as well in .NET 1.1, so don't let that stop you. I'm also assuming that you know how to write applications in .NET, either using Visual Studio 2005 or one of the free Visual Studio 2005 Express editions. I will be focusing mainly on Windows Forms applications, but again the Flickr.Net API library can be used just as well for Web applications, including those hosted in a Medium Trust environment (see my Web site for more details on Medium Trust).
I'm also assuming you are familiar with how to use Flickr and have an account there. If not, go GET ONE!
Get an API Key
To get started you will need to get an API Key for use with Flickr. You apply for new keys and manage your keys from the Your Keys section of the Flickr Services Web site at http://www.flickr.com/services/api/keys. Applying for a new key should be a pretty instantaneous affair. Once you get your API Key, you can return to the same page and click the Edit Configuration link. This will allow you to edit the description of the use of your API Key and show you your Shared Secret, which you will need if you want to perform authenticated requests to Flickr.
When running the examples below, you will have to replace the example API key with your own.
Get the Flickr.Net API Library
The Flickr.Net API Library can be downloaded from the Flickr.Net Web site. There is also a forum for posting your Flickr.Net specific questions (if they relate to the Flickr API in general you are better posting them on the Flickr API mailing list).
The download contains the source code for the library, as well as debug and release compiled DLLs. For the purposes of this article, we will use the release DLL, but you are free to add the source code project to your solution directly.
Flickr API Concepts
The Flickr API has a number of concepts and naming conventions that it would be useful to go over at this point.
Users
A user is uniquely identified by their User ID. This will look something like "40123132@N01." Where the Username is referred to, this is the same as your Screen name — the name that is displayed on your home page and which you can change at will. This should never be cached by your application because it can be changed at any time.
The final term is your Alias or the part of your Flickr URL that identified you. When you create an account this will be the same as your User ID (this URL will always work); you can specify a more user-friendly format for this URL once only.
Authentication
When you authenticate a user, Flickr gives you a Token. This token is unique for your API key, the user who you have authenticated, and the permissions they have given you (for example, read only or write access). This token will remain valid as long as the user does not revoke your authentication, and you should ideally cache this within your application.
Once authenticated, calls to Flickr will respond as if sent by that user and will show photos they have permission to see that others may not, such as private photos or their friends' and family's photos that have been marked for their eyes only. You will also be able to modify their photos, and upload new photos into their account.
Without authentication you can still do quite a lot of things, such as view all public photos, search for photos for users or by tag, and browse public groups.
Lists of Photos
When you perform a search on Flickr it often will not return all the photos in one go, but page the results. For example, if a search would usually return 1000 photos, it will return the details of the first 100 photos, then the next 100, and so on, for 10 pages. You can often specify the size of the page (the number of photos to return each time) and the page number to return; for example, if you set the page size (or PerPage property) to 500 you will only get 2 pages returned. In most cases 500 is the maximum, but check the Flickr API documentation for whatever the given method supports.
Go Flickr, Go
Create an Instance of Flickr
First, let's create a simple Flickr object, passing in your API key obtained above.
Visual C#
string apikey = "1234abcd1234abcd";
Flickr flickr = new Flickr(apikey);
Visual Basic
Dim apikey As String = "1234abcd1234abcd"
Dim f As Flickr = New Flickr(apikey)
From this instance of the Flickr object you can perform searches, browse groups, find users, and perform the steps required to authenticate a user (provided you provide the Shared Secret as well).
Find Those Photos
The following line of code searches all Flickr photos for photos with the tag "microsoft":
Visual C#
PhotoSearchOptions searchOptions = new PhotoSearchOptions();
searchOptions.Tags = "microsoft";
Photos microsoftPhotos = flickr.PhotosSearch(searchOptions);
Visual Basic
Dim searchOptions As PhotoSearchOptions = New PhotoSearchOptions()
searchOptions.Tags = "microsoft"
Dim microsoftPhotos As Photos = f.PhotosSearch(searchOptions)
The PhotoSearchOptions class is the easiest and most flexible way to search for photos. Many of its properties are optional, but it covers all the options available to the complex search function, including UserId, Tags, and SortOrder.
The Photos class contains a selection of properties, some of which may not be immediately obvious. As previously mentioned, when you perform a search on Flickr the result are paged. By default a page will be 100 photos big, and the above search will return the first 100 photos (or less if there are fewer than that) for the specified search. Photos.TotalPhotos will give you the total number of photos available on the current search, while Photos.TotalPages will give you the number of pages that you need to return to get all the available photos. By modifying the Page property of the PhotoSearchOptions class, you can return more pages from Flickr.
The following code returns the second and then the third page of results from Flickr for the above search:
Visual C#
searchOptions.Page = 2;
Photos microsoftPhotos2 = flickr.PhotosSearch(searchOptions);
searchOptions.Page = 3;
Photos microsoftPhotos3 = flickr.PhotosSearch(searchOptions);
Visual Basic
searchOptions.Page = 2
Dim microsoftPhotos2 As Photos = f.PhotosSearch(searchOptions)
searchOptions.Page = 3
Dim microsoftPhotos3 As Photos = f.PhotosSearch(searchOptions)
The Photos class also contains a PhotoCollection property, which is where the actual photos lie. You can add PhotoCollection objects together to collect together one or more page of results. You can also use the foreach statement to loop through all the photos in the collection.
Visual C#
PhotoCollection allPhotos = microsoftPhotos.PhotoCollection;
allPhotos.AddRange(microsoftPhotos2.PhotoCollection);
allPhotos.AddRange(microsoftPhotos3.PhotoCollection);
foreach (Photo photo in allPhotos)
{
Console.Write("Photos title is " + photo.Title);
}
Visual Basic
Dim allPhotos As PhotoCollection = microsoftPhotos.PhotoCollection
allPhotos.AddRange(microsoftPhotos2.PhotoCollection)
allPhotos.AddRange(microsoftPhotos3.PhotoCollection)
For Each p As Photo In allPhotos
Console.Write("Photos title is " & p.Title)
Next For
Find a User and Their Photos
To find a user you either have to search on their screen name or the URL of their home page (or use authentication, which we will get to later). If you have the screen name of a user (say "Sam Judson"), then the following will give you the User ID of that user.
Visual C#
string screenName = "Sam Judson";
FoundUser user = flickr.PeopleFindByUsername(screenName);
string userId = user.UserId;
Visual Basic
Dim screenName As String = "Sam Judson"
Dim user As FoundUser = f.PeopleFindByUsername(screenName)
Dim userId As String = user.UserId
This user ID can then be used to search that user's photos, favorites, groups, contacts, and so on. (Apologies to my British fans at the use of the American spelling of favorite throughout the API, but blame Flickr not me :-)
Visual C#
// First page of the users photos
// Sorted by interestingness
PhotoSearchOptions userSearch = new PhotoSearchOptions ();
userSearch.UserId = userId;
userSearch.Sort = SortOrder.InterestingnessAsc;
Photos usersPhotos = flickr.PhotosSearch(userSearch);
// Get users contacts
Contacts contacts = flickr.ContactsGetPublicList(userId);
// Get first page of a users favorites
Photos usersFavoritePhotos = flickr.FavoritesGetPublicList(userId);
// Get a list of the users groups
PublicGroupInfo[] usersGroups = flickr.PeopleGetPublicGroups(userId);
Visual Basic
' First page of the users photos
' Sorted by interestingness
Dim userSearch As PhotoSearchOptions = New PhotoSearchOptions()
userSearch.UserId = userId
userSearch.Sort = SortOrder.InterestingnessAsc
Dim usersPhotos As Photos = flickr.PhotosSearch(userSearch)
' Get users contacts
Dim contacts As Contacts = flickr.ContactsGetPublicList(userId)
' Get first page of a users favorites
Dim usersFavoritePhotos As Photos = flickr.FavoritesGetPublicList(userId)
' Get a list of the users groups
Dim usersGroups As PublicGroupInfo() = flickr.PeopleGetPublicGroups(userId)
I could sit here all day and list every method in the API, but basically if it's in the Flickr API, it's in the .Net library, and the method name will be the same as the Flickr method — but without the full stops and the flickr bit at the beginning. For example, "flickr.people.getPublicGroups" is "PeopleGetPublicGroups" in the Flickr.Net API Library.
Authentication
This perhaps is the most complex part of any application (at least in terms of interaction with Flickr), so we will cover it step-by-step. The example application provided at the end will have a complete implementation of desktop authentication in it. Web-based authentication is slightly different and is covered at the end.
Get the Frob
Frob? What the heck? I'm not quite sure what the word Frob means, but basically it's a temporary key that you can pass to Flickr, which will then ask the user to authenticate your application. Once it has been authenticated, you can use that same Frob to get the Authentication Token as well as the User ID of the authenticated user (see, told you we'd get back to that).
Tell the User Where to Go
After you have the Frob, you must pass this, along with your API Key and the permissions you need to Flickr, in a signed URL. Fortunately, the library has a method that does the signing for you and returns the URL to redirect the user to. You will however need to know your Shared Secret (see "Get an API Key" above if you haven't got your shared secret yet) to calculate this URL.
Example Code
Imagine you have two buttons on a form. The first reads Authenticate Me and the second reads Complete Authentication. The following code illustrates the code behind the form for the two buttons to authenticate a user for read/write permissions.
Visual C#
using FlickrNet;
// Store the Frob in a private variable
private string tempFrob;
private string ApiKey = "1234abcd1234abcd1234";
private string SharedSecret = "abcd1234abcd";
protected void AuthMeButton_Click(object sender, EventArgs e)
{
// Create Flickr instance
Flickr flickr = new Flickr(ApiKey, SharedSecret);
// Get Frob
tempFrob = flickr.AuthGetFrob();
// Calculate the URL at Flickr to redirect the user to
string flickrUrl = flckr.AuthCalcUrl(tempFrob, AuthLevel.Write);
// The following line will load the URL in the users default browser.
System.Diagnostics.Process.Start(flickrUrl);
}
protected void CompleteAuthButton_Click(object sender, EventArgs e)
{
// Create Flickr instance
Flickr flickr = new Flickr(ApiKey, SharedSecret);
try
{
// use the temporary Frob to get the authentication
Auth auth = flickr.AuthGetToken(tempFrob);
// Store this Token for later usage,
// or set your Flickr instance to use it.
Console.WriteLine("User authenticated successfully");
Console.WriteLine("Authentication token is " + auth.Token);
flickr.ApiToken = auth.Token;
Console.WriteLine("User id is " + auth.UserId);
}
catch(FlickrException ex)
{
// If user did not authenticat your application
// then a FlickrException will be thrown.
Console.WriteLine("User did not authenticate you");
Console.WriteLine(ex.ToString());
}
}
Visual Basic
Imports FlickrNet
' Store the Frob in a private variable
Private tempFrob As String
Private ApiKey As String = "1234abcd1234abcd1234"
Private SharedSecret As String = "abcd1234abcd"
Private Sub AuthMeButton_Click(ByVal sender As Object, ByVal e As EventArgs)
' Create Flickr instance
Dim f As Flickr = New Flickr(ApiKey, SharedSecret)
' Get Frob
tempFrob = f.AuthGetFrob()
' Calculate the URL at Flickr to redirect the user to
Dim flickrUrl As String = f.AuthCalcUrl(tempFrob, AuthLevel.Write)
' The following line will load the URL in the users default browser.
System.Diagnostics.Process.Start(flickrUrl)
End Sub
Private Sub CompleteAuthButton_Click(ByVal sender As Object, ByVal e As EventArgs)
' Create Flickr instance
Dim f As Flickr = New Flickr(ApiKey, SharedSecret)
Try
' use the temporary Frob to get the authentication
Auth a = f.AuthGetToken(tempFrob)
' Store this Token for later usage,
' or set your Flickr instance to use it.
Console.WriteLine("User authenticated successfully")
Console.WriteLine("Authentication token is " & a.Token)
f.ApiToken = a.Token
Console.WriteLine("User id is " & a.UserId)
Catch ex As FlickrException
' If user did not authenticat your application
' then a FlickrException will be thrown.
Console.WriteLine("User did not authenticate you")
Console.WriteLine(ex.ToString())
End Try
End Sub
As you can see, if the user does not authenticate you, then the AuthGetToken method throws an exception which can be caught to handle this situation.
Now You're Authenticated
Once you have authenticated and have the user's Token, two things can happen. Firstly, you can now call new methods that are only available when authenticated, such as Flickr.PhotosSetTags(), which sets the tags for a given photo of the authenticated user. You can also now upload photos to that user's account.
Secondly though, some methods will now perform slightly differently. For example, the above search for photos with the "microsoft" tag will now return any of that user's private photos that have that tag, as well as their public and other users' public photos with the tag.
Setting the token can also be done at the constructor stage, or later.
Visual C#
Flickr flickr = new Flickr(ApiKey, SharedSecret, AuthToken);
// or
flickr.ApiToken = newToken;
Visual Basic
Dim f As Flickr = New Flickr(ApiKey, SharedSecret, AuthToken)
' or
f.ApiToken = newToken
Web Authentication? Different How?
For Web-based authentication you must specify in the Edit Configuration page of your API key the page to redirect users to after they have authenticated your application. It's called the Callback URL. You also do not need to create a Frob when using Web-based authentication.
You can use the Flickr.AuthCalcWebUrl method to generate a URL to redirect the user to.
Visual C#
string url = flickr.AuthCalcWebUrl(AuthLevel.Write);
Response.Redirect(url);
Visual Basic
Dim url As String = f.AuthCalcWebUrl(AuthLevel.Write)
Response.Redirect(url)
In the page specified by the Callback URL above you get passed the Frob in the query string; for example, if your callback URL is http://example.com/flickr.aspx, then the user will be redirected to http://example.com/flickr.aspx?frob=1234abcd1234abcd.
Then you can use the Frob to get the authentication token as in the example above:
Visual C#
protected void Page_OnLoad(object sender, EventArgs e)
{
string frob = Request.QueryString["frob"];
Flickr flickr = new Flickr(ApiKey, SharedSecret);
Auth auth = flickr.AuthGetToken(frob);
// Store the token somewhere for later calls
}
Visual Basic
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim frob As String = Request.QueryString("frob")
Dim f As Flickr = New Flickr(ApiKey, SharedSecret)
Dim a As Auth = f.AuthGetToken(frob)
' Store the token somewhere for later calls
End Sub
Uploading Photos
Once you have authenticated a user, you can upload a photo to their account.
This is actually really simple to do. It can either be done directly from a file on the hard drive or from a Stream object.
Visual C#
string file = "test.jpg";
string title = "Test Photo";
string descripton = "This is the description of the photo";
string tags = "tag1,tag2,tag3";
string photoId = flickr.UploadPicture(file, title, dscription, tags);
Visual Basic
Dim file As String = "test.jpg"
Dim title As String = "Test Photo"
Dim descripton As String = "This is the description of the photo"
Dim tags As String = "tag1,tag2,tag3"
Dim photoId As String = f.UploadPicture(file, title, dscription, tags)
The method has parameters for setting the photo's title, description, tags, and whether the photo is public of private (three optional Boolean parameters not shown above).
Updating Photos
Once you've uploaded some a photo you might want to add it to a set, add it to a group or two, or update the description, title or add some tags.
The following code updates the title and description of the previously uploaded photo, and then adds it to the first set in the user's list of sets.
Visual C#
flickr.PhotosSetMeta(photoId, "New Title", "New Description");
// Get list of users sets Photosets sets = flickr.PhotosetsGetList();
// Get the first set in the collection
Photoset set = sets.PhotosetCollection[0];
// Add the photo to that set
flickr.PhotosetsAddPhoto(set.PhotosetId, photoId);
Visual Basic
f.PhotosSetMeta(photoId, "New Title", "New Description")
' Get list of users sets
Dim sets As Photosets = f.PhotosetsGetList();
' Get the first set in the collection
Dim set As Photoset = sets.PhotosetCollection(0)
' Add the photo to that set
f.PhotosetsAddPhoto(set.PhotosetId, photoId)
Conclusion
As you can see, the actual mechanics of communicating with Flickr are relatively simple. The hard part is coming up with the idea for a groovy new application.
In the second part of this application, I will develop an application based on the WIA Coding 4 Fun article Look at Me! Windows Image Acquisition, which you could use to automatically upload images when you connect a compatible device to your computer.