SharePoint: Creating HttpHandler for user profile images
I have custom authentication and user profiles solution where user profiles are stored in list. This list is directly accessible only to administrators. Users can register to site and modify their profiles through special pages that run profile operations under elevated privileges. Users have three versions of their avatar: 64x64, 32x32 and 16x16. These avatars are saved as user profile attachments when user uploads his or her avatar. Because avatars are used at almost every page in portal I wrote IHttpHandler that provides avatars based on user profile ID.
Here is shortened draft version of my code (I removed some complex guard checks that use custom extensions methods for SharePoint objects).
public class ProfileImageHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
var request = context.Request;
var response = context.Response;
var idString = request.QueryString["id"];
var sizeString = request.QueryString["size"];
var id = 0;
int.TryParse(idString, out id);
var siteId = SPContext.Current.Site.ID;
var sec = new SPSecurity.CodeToRunElevated(delegate()
{
using (var site = new SPSite(siteId))
{
using (var web = site.OpenWeb())
{
if (id == 0)
{
OutputDefaultImage(web, response);
response.End();
return;
}
var list = web.Lists["ProfileList"];
var item = list.GetItemById(id);
sizeString = sizeString + "x" + sizeString;
foreach (string fileName in item.Attachments)
{
if (!fileName.Contains(sizeString))
continue;
var fileUrl = item.Attachments.UrlPrefix + fileName;
var file = web.GetFile(fileUrl);
var stream = file.OpenBinaryStream();
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
response.Clear();
response.ContentType = "image/png";
response.BinaryWrite(bytes);
stream.Dispose();
response.End();
}
}
}
}
);
SPSecurity.RunWithElevatedPrivileges(sec);
}
private void OutputDefaultImage(SPWeb web, HttpResponse response)
{
var defaultFileUrl = "/Style Library/portal/images/user.gif";
var defaultFile = web.GetFile(defaultFileUrl);
var defaultFileStream = defaultFile.OpenBinaryStream();
var defaultBytes = new byte[defaultFileStream.Length];
defaultFileStream.Read(defaultBytes, 0, defaultBytes.Length);
response.Clear();
response.ContentType = "image/png";
response.BinaryWrite(defaultBytes);
defaultFileStream.Dispose();
}
}
The code here works as follows. It retrieves user profile by id and checks if profile has image with given width and height. Avatars in this system are squares so I need to know only size of one side. If user profile doesn’t have attachment that contains size x size (by example “32x32”) in its name then default profile image is returned.
Let’s suppose we have user profile (id = 176) and we want 32x32 size avatar for this profile. Also let’s assume there is userimagehandler.ashx file in the folder portalhandlers. We can ask 32x32 avatar by using the following request.
/_layouts/portalhandlers/userimagehandler.ashx?size=32&id=176
As URL for each avatar size is unique for each profile then it is also possible to cache avatars so there is no need to read them from content database per every request.
|
|
|
|
|
|
|