上载用户配置文件图片示例 SharePoint 外接程序
Core.ProfilePictureUploader 示例显示了如何从文件共享或 SharePoint Online URL 执行用户配置文件数据的批量上载,以及如何将用户配置文件属性链接到已上载的图像。
使用此示例以了解如何:
- 将用户的配置文件图片从 SharePoint Server 内部部署迁移到 SharePoint Online。
- 解决 Azure Active Directory 同步工具(目录同步)未能将用户的配置文件图像同步到 SharePoint Online 时所发生的问题。
- 替换 SharePoint Online 中质量较差的用户配置文件图片。
本示例使用控制台应用程序执行以下操作:
- 从用户映射文件读取用户名和图像文件路径或 URL。
- 提取一个或三个图像并将其上载到“我的网站宿主”上的图片库。
- 设置用户配置文件属性,将已上传的图像链接到用户的配置文件。
- 更新其他(可选)的用户配置文件属性。
准备工作
首先,从 GitHub 上的 Office 365 开发人员模式和做法项目下载 Core.ProfilePictureUploader 示例外接程序。
注意
本文中的代码按原样提供,不提供任何明示或暗示的担保,包括对特定用途适用性、适销性或不侵权的默示担保。
运行此代码示例之前
- 存储想要上载到文件共享或 Web 服务器上的 SharePoint Online 的用户图像。
- 编辑 userlist.csv 文件以包括以下内容:
- 一个包含值 UserPrincipalName、SourceURL 的标题行。
- 针对每个用户,添加一个新行,其中包含用户的组织帐户(或用户主体名称)以及文件路径或要上传的图像的 URL。
从 Visual Studio 运行此示例
使用以下命令行参数 -SPOAdmin Username -SPOAdminPassword Password -Configuration filepath
来配置 Core.ProfilePictureUploader 项目,其中:
- Username 是你的 Office 365 管理员的用户名。
- Password 是你的 Office 365 管理员的密码。
- Filepath 是 configuration.xml 文件的文件路径。
在 Core.ProfilePictureUploader 项目上设置命令行参数
在 解决方案资源管理器 中,打开快捷菜单, (右键单击 Core.ProfilePictureUploader 项目>“属性”) 。
选择“调试”。
在“命令行参数”中,输入前面列出的命令行参数。
根据你的要求配置上载过程
通过输入以下值来编辑 configuration.xml 文件:
你的 Office 365 租户在 tenantName 元素中的名称。 例如:
<tenantName>contoso.onmicrosoft.com</tenantName>
pictureSourceCsv 元素中的用户映射文件路径。 例如:
<pictureSourceCsv>C:\temp\userlist.csv</pictureSourceCsv>
使用 thumbs 元素的图像上载说明。 编辑 thumbs 元素中的以下属性:
aupload3Thumbs – 如果想要为每个用户上传 3 张图像,请将其设置为 true;如果只想上传一张图像,请将其设置为 false。
createSMLThumbs - 若要通过源图像创建三个大小不同的图像(小、中和大),请设置为 true;若要上传三个大小相同的图像,请设置为 false。
要使用 additionalProfilePropties 元素对用户配置文件设置的其他属性。 例如,下面的 XML 额外指定了一个名为 SPS-PictureExchangeSyncState 的用户配置文件属性。当代码示例运行时,应在用户配置文件上将此属性设置为零。
<additionalProfileProperties> <property name="SPS-PictureExchangeSyncState" value="0"/> </additionalProfileProperties>
logfile 元素中的日志文件路径,如下面的示例所示。
<logFile path="C:\temp\log.txt" enableLogging="true" loggingLevel="verbose" />
上载使用 uploadDelay 元素的不同图像文件之间的上载延迟(以毫秒为单位)。 uploadDelay 的建议设置为 500 毫秒。
在 App.config 文件中,更改 ProfilePictureUploader_UPSvc_UserProfileService 设置的值元素,以包含对 SharePoint Online 管理中心中用户配置文件服务的引用,如以下示例所示。
<Contoso.Core.ProfilePictureUploader.Properties.Settings>
<setting name="ProfilePictureUploader_UPSvc_UserProfileService"
serializeAs="String">
<value>https://contoso-admin.sharepoint.com/_vti_bin/userprofileservice.asmx</value>
</setting>
</Contoso.Core.ProfilePictureUploader.Properties.Settings>
重要
通过连接到 SharePoint Online 管理中心上的 userprofileservice.asmx Web 服务,可以更新其他用户的用户配置文件属性。 运行此代码示例时,请使用有权管理用户配置文件的 Office 365 管理员帐户。
使用 Core.ProfilePictureUploader 示例外接程序
此代码示例将作为控制台应用程序运行。 代码示例运行后,Program.cs 中的 Main 方法将执行以下操作:
使用 SetupArguments 和 InitializeConfiguration 初始化控制台应用程序。
调用 InitializeWebService 以连接到 SharePoint Online 中的用户配置文件服务。
循环访问 userlist.csv 文件,以读取用户的用户主体名称 (UPN) 和用户图像文件的位置。
使用 GetImagefromHTTPUrl 中的 WebRequest 和 WebResponse 对象提取用户的图像。
调用 UploadImageToSpo 将用户的图像上载到 SharePoint Online。
调用 SetMultipleProfileProperties 以设置用户的 PictureURL 和 SPS-PicturePlaceholderState 用户配置文件属性。
调用 SetAdditionalProfileProperties,在上载图像文件后对用户配置文件设置其他属性。
static void Main(string[] args)
{
int count = 0;
if (SetupArguments(args)) // Checks if args passed are valid
{
if (InitializeConfiguration()) // Check that the configuration file is valid
{
if (InitializeWebService()) // Initialize the web service end point for the SharePoint Online user profile service.
{
using (StreamReader readFile = new StreamReader(_appConfig.PictureSourceCsv))
{
string line;
string[] row;
string sPoUserProfileName;
string sourcePictureUrl;
while ((line = readFile.ReadLine()) != null)
{
if (count > 0)
{
row = line.Split(',');
sPoUserProfileName = row[0];
sourcePictureUrl = row[1];
LogMessage("Begin processing for user " + sPoUserProfileName, LogLevel.Warning);
// Get source picture from source image path.
using (MemoryStream picturefromExchange = GetImagefromHTTPUrl(sourcePictureUrl))
{
if (picturefromExchange != null) // If we got image, upload to SharePoint Online
{
// Create SharePoint naming convention for image file.
string newImageNamePrefix = sPoUserProfileName.Replace("@", "_").Replace(".", "_");
// Upload source image to SharePoint Online.
string spoImageUrl = UploadImageToSpo(newImageNamePrefix, picturefromExchange);
if (spoImageUrl.Length > 0)// If upload worked:
{
string[] profilePropertyNamesToSet = new string[] { "PictureURL", "SPS-PicturePlaceholderState" };
string[] profilePropertyValuesToSet = new string[] { spoImageUrl, "0" };
// Set these two required user profile properties - path to uploaded image, and pictureplaceholder state.
SetMultipleProfileProperties(_sPOProfilePrefix + sPoUserProfileName, profilePropertyNamesToSet, profilePropertyValuesToSet);
// Set additional user profile properties based on your requirements.
SetAdditionalProfileProperties(_sPOProfilePrefix + sPoUserProfileName);
}
}
}
LogMessage("End processing for user " + sPoUserProfileName, LogLevel.Warning);
int sleepTime = _appConfig.UploadDelay;
System.Threading.Thread.Sleep(sleepTime); // A pause between uploads is recommended.
}
count++;
}
}
}
}
}
LogMessage("Processing finished for " + count + " user profiles", LogLevel.Information);
}
InitializeWebService 连接到 SharePoint Online,并设置 User Profile Service 对实例变量的引用。 此代码示例中的其他方法使用这个实例变量,对用户配置文件属性应用更新。 为了管理用户配置文件,此代码示例使用 SharePoint Online 管理中心内的 userprofileservice.asmx Web 服务。
static bool InitializeWebService()
{
try
{
string webServiceExt = "_vti_bin/userprofileservice.asmx";
string adminWebServiceUrl = string.Empty;
// Append the web service (ASMX) URL onto the admin website URL.
if (_profileSiteUrl.EndsWith("/"))
adminWebServiceUrl = _profileSiteUrl + webServiceExt;
else
adminWebServiceUrl = _profileSiteUrl + "/" + webServiceExt;
LogMessage("Initializing SPO web service " + adminWebServiceUrl, LogLevel.Information);
// Get secure password from clear text password.
SecureString securePassword = GetSecurePassword(_sPoAuthPasword);
// Set credentials from SharePoint Client API, used later to extract authentication cookie, so can replay to web services.
SharePointOnlineCredentials onlineCred = new SharePointOnlineCredentials(_sPoAuthUserName, securePassword);
// Get the authentication cookie by passing the URL of the admin website.
string authCookie = onlineCred.GetAuthenticationCookie(new Uri(_profileSiteUrl));
// Create a CookieContainer to authenticate against the web service.
CookieContainer authContainer = new CookieContainer();
// Put the authenticationCookie string in the container.
authContainer.SetCookies(new Uri(_profileSiteUrl), authCookie);
// Set up the user profile web service.
_userProfileService = new UPSvc.UserProfileService();
// Assign the correct URL to the admin profile web service.
_userProfileService.Url = adminWebServiceUrl;
// Assign previously created authentication container to admin profile web service.
_userProfileService.CookieContainer = authContainer;
// LogMessage("Finished creating service object for SharePoint Online Web Service " + adminWebServiceUrl, LogLevel.Information);
return true;
}
catch (Exception ex)
{
LogMessage("Error initiating connection to profile web service in SPO " + ex.Message, LogLevel.Error);
return false;
}
}
Program.cs 中的 Main 方法调用 UploadImageToSpo,将用户配置文件图片上载到 SharePoint Online。 所有用户配置文件图片都存储在“我的网站”主机上的图片库中。 UploadImageToSpo 执行下列任务:
- 连接到 SharePoint Online。
- 确定要为每个用户上载的图像数量。
- 如果已将应用程序配置为每个用户上载一个图像,那么图像会上载到图片库中。
- 如果已将应用程序配置为每个用户上载三个图像,那么应用程序会检查配置文件中的 createSMLThumbs 值,以确定是否必须上载三个大小不同的图像。 如果必须上载三个大小不同的图像,应用程序会使用 ResizeImageSmall 和 ResizeImageLarge,通过源图像创建三个大小不同的图像。 然后,应用会将重设大小后的图像上传到图片库中。 如果不需要三个大小不同的图像,应用会将三个大小相同的图像上传到图片库中。
static string UploadImageToSpo(string PictureName, Stream ProfilePicture)
{
try
{
string spPhotoPathTempate = "/User Photos/Profile Pictures/{0}_{1}Thumb.jpg"; // Path template to picture library on the My Site host.
string spImageUrl = string.Empty;
// Create SharePoint Online Client context to My Site host.
ClientContext mySiteclientContext = new ClientContext(_mySiteUrl);
SecureString securePassword = GetSecurePassword(_sPoAuthPasword);
// Provide authentication credentials using Office 365 authentication.
mySiteclientContext.Credentials = new SharePointOnlineCredentials(_sPoAuthUserName, securePassword);
if (!_appConfig.Thumbs.Upload3Thumbs) // Upload a single input image only to picture library, no resizing necessary.
{
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "M");
LogMessage("Uploading single image, no resize, to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, ProfilePicture, true);
}
else if (_appConfig.Thumbs.Upload3Thumbs && !_appConfig.Thumbs.CreateSMLThumbs)// Upload three images of the same size.
{
// The following code is not optimal. Upload the same source image three times with different names.
// No resizing of images necessary.
LogMessage("Uploading threes image to SPO, no resize", LogLevel.Information);
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "M");
LogMessage("Uploading medium image to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, ProfilePicture, true);
ProfilePicture.Seek(0, SeekOrigin.Begin);
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "L");
LogMessage("Uploading large image to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, ProfilePicture, true);
ProfilePicture.Seek(0, SeekOrigin.Begin);
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "S");
LogMessage("Uploading small image to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, ProfilePicture, true);
}
else if (_appConfig.Thumbs.Upload3Thumbs && _appConfig.Thumbs.CreateSMLThumbs) //Generate 3 different sized images.
{
LogMessage("Uploading threes image to SPO, with resizing", LogLevel.Information);
// Create three images based on recommended sizes for SharePoint Online.
// Create small-sized image.
using (Stream smallThumb = ResizeImageSmall(ProfilePicture, _smallThumbWidth))
{
if (smallThumb != null)
{
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "S");
LogMessage("Uploading small image to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, smallThumb, true);
}
}
// Create medium-sized image.
using (Stream mediumThumb = ResizeImageSmall(ProfilePicture, _mediumThumbWidth))
{
if (mediumThumb != null)
{
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "M");
LogMessage("Uploading medium image to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, mediumThumb, true);
}
}
// Create large-sized image. This image is shown when you open the user's OneDrive for Business.
using (Stream largeThumb = ResizeImageLarge(ProfilePicture, _largeThumbWidth))
{
if (largeThumb != null)
{
spImageUrl = string.Format(spPhotoPathTempate, PictureName, "L");
LogMessage("Uploading large image to " + spImageUrl, LogLevel.Information);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(mySiteclientContext, spImageUrl, largeThumb, true);
}
}
}
// Return URL of the medium-sized image to set properties on the user profile.
return _mySiteUrl + string.Format(spPhotoPathTempate, PictureName, "M");
}
catch (Exception ex)
{
LogMessage("User Error: Failed to upload thumbnail picture to SPO for " + PictureName + " " + ex.Message, LogLevel.Error);
return string.Empty;
}
}
SetMultipleProfileProperties 在一个方法调用中设置多个用户配置文件属性。 在此代码示例中,SetMultipleProfileProperties 为用户设置以下用户配置文件属性:
PictureURL - 设置为已上载到“我的网站”主机上图片库中的中等大小图像的 URL。
SPS-PicturePlaceholderState - 设置为零,指明 SharePoint Online 应为用户显示上载的图片。
static void SetMultipleProfileProperties(string UserName, string[] PropertyName, string[] PropertyValue)
{
LogMessage("Setting multiple SPO user profile properties for " + UserName, LogLevel.Information);
try
{
int arrayCount = PropertyName.Count();
UPSvc.PropertyData[] data = new UPSvc.PropertyData[arrayCount];
for (int x = 0; x < arrayCount; x++)
{
data[x] = new UPSvc.PropertyData();
data[x].Name = PropertyName[x];
data[x].IsValueChanged = true;
data[x].Values = new UPSvc.ValueData[1];
data[x].Values[0] = new UPSvc.ValueData();
data[x].Values[0].Value = PropertyValue[x];
}
_userProfileService.ModifyUserPropertyByAccountName(UserName, data);
// LogMessage("Finished setting multiple SharePoint Online user profile properties for " + UserName, LogLevel.Information);
}
catch (Exception ex)
{
LogMessage("User Error: Exception trying to update profile properties for user " + UserName + "\n" + ex.Message, LogLevel.Error);
}
}
SetAdditionalProfileProperties 设置要在上载图像文件后更新的其他任何用户配置文件属性。 可以在 configuration.xml 文件中指定要更新的其他属性。
static void SetAdditionalProfileProperties(string UserName)
{
if (_appConfig.AdditionalProfileProperties.Properties == null) // If there are no additional properties to update.
return;
int propsCount = _appConfig.AdditionalProfileProperties.Properties.Count();
if (propsCount > 0)
{
string[] profilePropertyNamesToSet = new string[propsCount];
string[] profilePropertyValuesToSet = new string[propsCount];
// Loop through each property in configuration file.
for (int i = 0; i < propsCount; i++)
{
profilePropertyNamesToSet[i] = _appConfig.AdditionalProfileProperties.Properties[i].Name;
profilePropertyValuesToSet[i] = _appConfig.AdditionalProfileProperties.Properties[i].Value;
}
// Set all properties in a single call.
SetMultipleProfileProperties(UserName, profilePropertyNamesToSet, profilePropertyValuesToSet);
}
}