在自己的代码中获取SharePoint的存储占用情况

如果我们想要关注SharePoint网站中的存储使用情况的话,SharePoint中可以使用spSite.Usage获取当前网站集的存储占用情况(这是一个名为UsageInfo的结构,它的Storage属性就是网站集占用的字节数)。

但是通过这种方法我们只能得到网站集的存储使用情况,无法得到更细粒度比如网站、文档库、文件夹使用了多少存储空间(需要注意的是,一个文件所占用的存储空间不一定是这个文件的大小,如果你开启了版本控制的话,那么所有的版本都应该计算到占用的存储空间中)。

在SharePoint 2010 SP1中,新增了一个叫Storage Metric的功能(中文版不恰当地翻译成了“存储标准”),可以看到网站集中每一级别所使用的存储空间(详细介绍可以参考我之前写过的这篇Blog:SharePoint 2010 SP1新功能(存储标准))。

但遗憾的是,这个新增功能的涉及到的所有代码都是internal的,它在数据库里新增的两个表结构都很简单,但是那个存储过程比较复杂,也很难直接从这个方法去获取,因此,就只剩下了一个选择:反射。

通过反射的方法,我们可以调用SPSite中的内部方法GetStorageMetrics,它会返回一个SPStorageMetricsResult的类,里面的Children属性中是一个List<SPStorageMetricItem>,这一些东西都是internal的,但都可以通过反射来获取到。

我为SPSite扩展了一个同名的方法GetStorageMetrics,实现这个功能,完整的代码如下(单独的cs文件下载点我点我):

   1: using System;
   2: using System.Collections;
   3: using System.Collections.Generic;
   4: using System.Linq;
   5: using System.Reflection;
   6: using System.Text;
   7: using Microsoft.SharePoint;
   8:  
   9: namespace Erucy.Utilities
  10: {
  11:     public class SPStorageMetricItem
  12:     {
  13:         public enum MetricType
  14:         {
  15:             Invalid = -1,
  16:             File = 0,
  17:             Folder = 1,
  18:             Web = 2
  19:         }
  20:  
  21:         public string DisplayName { get; private set; }
  22:         public Guid Id { get; private set; }
  23:         public DateTime LastModified { get; private set; }
  24:         public long? TotalSize { get; private set; }
  25:         public MetricType Type { get; private set; }
  26:         public string Url { get; private set; }
  27:         public Guid WebId { get; private set; }
  28:  
  29:         public SPStorageMetricItem(object metricObj)
  30:         {
  31:             this.DisplayName = (string)GetPropValue(metricObj, "DisplayName");
  32:             this.Id = (Guid)GetPropValue(metricObj, "Id");
  33:             this.LastModified = (DateTime)GetPropValue(metricObj, "LastModified");
  34:             this.TotalSize = (long?)GetPropValue(metricObj, "TotalSize");
  35:             this.Url = (string)GetPropValue(metricObj, "Url");
  36:             this.WebId = (Guid)GetPropValue(metricObj, "WebId");
  37:  
  38:             string itemType = Convert.ToString(GetPropValue(metricObj, "Type"));
  39:             switch (itemType)
  40:             {
  41:                 case "File":
  42:                     this.Type = MetricType.File;
  43:                     break;
  44:                 case "Folder":
  45:                     this.Type = MetricType.Folder;
  46:                     break;
  47:                 case "Web":
  48:                     this.Type = MetricType.Web;
  49:                     break;
  50:                 default:
  51:                     this.Type = MetricType.Invalid;
  52:                     break;
  53:             }
  54:         }
  55:  
  56:         private object GetPropValue(object obj, string propertyName)
  57:         {
  58:             PropertyInfo propInfo = obj.GetType().GetProperty(propertyName,
  59:                 BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.ExactBinding);
  60:             return propInfo.GetValue(obj, null);
  61:         }
  62:     }
  63:  
  64:     public static class StorageMetricExtension
  65:     {
  66:         public static List<SPStorageMetricItem> GetStorageMetrics(this SPSite site, string root, int orderBy, bool isAscending)
  67:         {
  68:             MethodInfo getMetricMethod = typeof(SPSite).GetMethod("GetStorageMetrics", 
  69:                 BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.ExactBinding);
  70:             object metricResultObj = getMetricMethod.Invoke(site, new object[] { root, orderBy, isAscending });
  71:  
  72:             PropertyInfo childrenProperty = metricResultObj.GetType().GetProperty("Children", 
  73:                 BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.ExactBinding);
  74:             IList rawMetricItems = childrenProperty.GetValue(metricResultObj, null) as IList;
  75:  
  76:             List<SPStorageMetricItem> result = new List<SPStorageMetricItem>(rawMetricItems.Count);
  77:             foreach (object metricObj in rawMetricItems)
  78:             {
  79:                 result.Add(new SPStorageMetricItem(metricObj));
  80:             }
  81:             return result;
  82:         }
  83:     }
  84: }

其中的SPStorageMetricItem类和SharePoint内置的那个internal类基本上是一致的,可以获取到相关的信息,包括:

  • DisplayName:名称
  • Url:Url地址
  • LastModified:最后修改时间
  • Id:对象的Guid(如果对象是网站/列表的话,这个Id并不是网站/列表ID,而是他们的根文件夹的ID)
  • WebId:所在网站的Id
  • Type:类型,包括网站、文件夹、文件
  • TotalSize:对象占用的存储空间,以字节为单位

在使用的时候很简单,有三个参数:

  • root:根路径,方法会返回这个路径中所有子网站和子文件夹、文件所占用的大小空间,使用相对服务器的路径
  • orderBy:排序(这个原本是一个internal的枚举,我就偷懒直接用int了),0是按照TotalSize排序,1是按照LastModified排序
  • isAscending:正序或逆序

这个在使用的过程中会有如下几个需要考虑的问题:

1、因为使用了反射,所以速度会有点慢

2、必须是SharePoint 2010 SP1以及之后的版本(因为功能是在SP1才有的)

3、如果root参数不是网站的话(比如你想获取一个文档库中若干文件夹占用的存储空间),运行在非IIS进程中的时候会报错。这个和SharePoint底层那个COM的实现有关,没什么解决办法。

posted on 2012-05-30 17:27  Erucy  阅读(728)  评论(0编辑  收藏  举报

导航