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: 64×64, 32×32 and 16×16. 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 “32×32”) in its name then default profile image is returned.

Let’s suppose we have user profile (id = 176) and we want 32×32 size avatar for this profile. Also let’s assume there is userimagehandler.ashx file in the folder portalhandlers. We can ask 32×32 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.


Leave a Reply

Your email address will not be published. Required fields are marked *