Friday, August 20, 2010

Limit the size of upload document in sharepoint

Scenario
Customer requirment for limit the size of file upload in image or document library of sharepoint.This is a common requirment for most of the customers.How we handle the validation?

Solution
Most of the sharepoint developer first thought will be eventhandler.When you start diving into deep you will realise that some of the object web developers love to use are null.when you try to access the object like  HttpContext and SPContext it will be null.So you have to think alternatives before start validation coding in event handlers.

Event handlers allows you to access all the items in sharepoint object model but not in a straight forward way. SPItemEventProperties properties is nice little object helps you achive most of the objects you are looking.Yous should use this object wiseley to achieve the goals you are looking for.Following member of SPItemEventProperties is usefull when you are writing code in Event Handler
 * AfterProperties
 * AfterUrl
 * BeforeProperties
 * BeforeUrl
 * ListItem
 * UserDisplayName
 * UserLoginName
 * WebUrl
 * OpenWeb()

All these properties are usefull but we need to know which is the best place to use thes.First we need to understand the type of event classification in sharepoint.There are mainly two types assynchronus and synchronus events we need to pick them carefully based on the requirment.I will advise to use Synchronus events over assynchronus events.If you have multiple user working on same file then assynchronus events will defeat the purpose in some scenarios.Synchronus events are end with "ing" ex: ItemAdding,ItemUpdating etc Assynchronus events are ends with "ed" Ex: ItemAdded,ItemUpdated etc.
Let see how we will handle our current requirment, before start writing the code we need to find which objects and properties are avaialable in each events.Lets take two events ItemAdding and ItemUpdating
 * ItemAdding
      SPContext - Null
      HttpContext - Null
      SPItemEventProperties
          properties.ListItem - Null
          properties.AfterProperties - (Usefull to get basic properties of  item)
          properties.BeforeProperties -(No Use in this event)
          properties.OpenWeb() - (Usefull to get the SPWebObject)

* ItemUpdating

   SPContext - Null
   HttpContext - Null
   SPItemEventProperties
         properties.ListItem - SPListItem object
         properties.AfterProperties - (Usefull to get after properties of item )
         properties.BeforeProperties -(Usefull to get before properties of item)
         properties.OpenWeb() - (Usefull to get the SPWebObject)

From above we could conclude that event handling code writing is not just copy paste one.In our scenario, we have to handle the validation in a flexible way. So it could handle validation from itemadding as well as item updating event.How we will get File size ? Its tricky but simple .

ItemAdding Event
   properties.AfterProperties["vti_filesize"]

ItemUpdatingEvent
  properties.ListItem.File.TotalLength

Following function "ValidFile" can be called from ItemAdding or ItemUpdating event and pass the properties (SPItemEventProperties ) object.The function will check the following

1. Libraray Title is "Images" then only execute the validation (common scenario for most of the requirement)
2. Current User is Site Admin or not if the user is SiteAdmin then give a validation exemption
3. Read the maximum size of the file from web.config and validate the file size against it.

Feel free to make changes to the function and use for you requirments.
private bool ValidFile(SPItemEventProperties properties)



{


long validFileSize;


long currentFileSize;






if (properties.ListItem == null)


{


using (SPWeb web = properties.OpenWeb())


{


if (!web.CurrentUser.IsSiteAdmin)


{


if (properties.ListTitle.ToLower() == "images")


{


if (ConfigurationManager.AppSettings["FileSize"] != null)


{
   validFileSize = long.Parse(ConfigurationManager.AppSettings["FileSize"].ToString());


}
else


{


validFileSize = 1000000;//1MB


}






currentFileSize = long.Parse(properties.AfterProperties["vti_filesize"].ToString());


if (currentFileSize > validFileSize)


{


return false;


}


}


}






}


}


else if (properties.ListItem.ParentList.Title.ToLower() == "images")


{


if (!properties.ListItem.Web.CurrentUser.IsSiteAdmin)


{
if (ConfigurationManager.AppSettings["FileSize"] != null)


{
validFileSize = long.Parse(ConfigurationManager.AppSettings["FileSize"].ToString());

}


else


{


validFileSize = 1000000;//1MB

}
currentFileSize = properties.ListItem.File.TotalLength;

if (currentFileSize > validFileSize)


{


return false;

}

}


}

return true;


} 

Cheers
Shyju Mohan

1 comment:

Harish Kumar said...

Hi,

This solution is not working..

properties.AfterProperties["vti_filesize"].ToString() will returns null.