迁移TFS,批量将文档导入SharePoint 2013 文档库

简介:

一、需求分析

公司需要将存在于旧系统(TFS)所有的文档迁移至新系统(SharePoint 2013)。现已经将50G以上的文档拷贝到SharePoint 2013 Server上。这些文档是一些不规则的资料,除了常见的Office文件、PDF,还包括图片、RAR等,甚至还包括一些快捷方式(.link)这类的"脏数据"。除此之外,这些存在于TFS中的文档,名称也是"不规则",即包含了SharePoint 2013文档命名不支持的字符如"&", "\"", "?", "<", ">", "#", "{", "}", "%", "~", "/", "\\"。所以,这对导入又增加了复杂度。

了解了文档内容和命名规则后,接下来就是分析怎样导入至SharePoint文档库中:

  • 首先,每一个二级文件夹的命名是有规则的,正好是项目编号(Project Number),如GCP-xxxx-xxx-xxx。再根据此编号创建一个子站点。
  • 值得一提的是,根据编号创建的子站点并不是随意创建的,而是需要考虑究竟要在哪一个Site Collection下创建子站点,并且还要给予独立权限的分配,即为子站点打断权限继承,为其增加两个组(Owners和Members),并向组里添加对应的人员。
  • 对应的创建规则存在于如下List中

其中Project Number即项目编号,与TFS中文件夹的名称一致。Department 即需要将此子站点创建于哪个Site Collection中,包含两个值SMO和CO。PM列是一个Person Or Group类型的字段,需要将此字段的值加入到Owner组,Domain Group列也是一个Person Or Group类型的字段,需要将此字段的值加入到Member组中。

  • 接下来,是最重要的一步,找到最佳实践去创建各个Level的文件夹并传入文档。

二、分析和构建导入程序

首先,文件夹的目录结构如下图所示:

文档目录结构图

  • 根据上图文档目录结构图,分割字符串(E:\TFS\GCP0401-S\4.Project Management\3 Document Management\TMF),获取文件夹的名称,即Project Number(GCP0401-S)。然后根据此Project Number找到对应的Department、PM、Domain Group,最后创建子站点。逻辑代码如下图所示:

 

  • 从上文档目录结构图可以分析出,二级目录是项目编号,即对应要创建的子站点。在此目录下有"无限级"的子文件夹。那应该怎样在子站点的文档库中创建如此多的文件夹呢,这需要好好考虑一下。对,用递归,得到每一个分支最底层的文件夹路径即可。具体实现如下所示:
复制代码
private void GetDeepestFoleder(string sDir)
        {
            string dir = string.Empty;
            try
            {
                foreach (string path in Directory.GetDirectories(sDir))
                {
                    dir = path;

                    if (!arrayList.Contains(dir))
                    {
                        arrayList.Add(dir);
                    }

                    arrayList.Remove(dir.Substring(0, dir.LastIndexOf("\\")));

                    GetDeepestFoleder(dir);
                }
            }
            catch (Exception excpt)
            {
                logger.Debug(excpt.ToString());
            }
        }
复制代码
  • 得到所有最内层文件夹的URL之后,接着就是在SharePoint 文档库中创建一级一级的文件夹了。
  • 以上代码逻辑中包含了字符串的处理,因为SharePoint 2013的文档、文件夹命名有严格的要求,不能包含非法字符。并且也不能以字符 "."开始或者结束。所以添加了字符串处理操作功能。
复制代码
 public static class MyStringExtention
    {
        public static string Clean(this string s)
        {
            StringBuilder sb = new StringBuilder(s);
            //"&", "\"", "?", "<", ">", "#", "{", "}", "%", "~", "/", "\\" uu.uu可以,但uu.就不行
            sb.Replace("&", "-");
            sb.Replace("\"", "-");
            sb.Replace("?", "-");
            sb.Replace("<", "-");
            sb.Replace(">", "-");
            sb.Replace("#", "-");
            sb.Replace("{", "-");
            sb.Replace("}", "-");
            sb.Replace("%", "-");
            sb.Replace("~", "-");
            sb.Replace("/", "-");
            sb.Replace("\\", "-");
           // sb.Replace(".", "-");

            return sb.ToString();
        }
    }
复制代码
  • 在成功创建了子站点并在文档库中创建了所有文件夹后,接下来就是将文档上传至指定的文件夹中了。所以接下来, 需要获取指定目录下所有的文件,我使用了一个队列来保存文件路径, 而不是使用递归或者使用.NET 4.0提供的基于文件迭代的功能(Directory.EnumerateFiles)来获取所有文件,原因有2点:
    • Directory.EnumerateFiles内置的递归方法容易抛出异常,比如没有权限访问等。
    • Queue<String> 避免了多次递归时调用堆栈从而会创建大数组。
复制代码
 private IEnumerable<string> GetFiles(string path)
        {
            Queue<string> queue = new Queue<string>();
            queue.Enqueue(path);
            while (queue.Count > 0)
            {
                path = queue.Dequeue();
                try
                {
                    foreach (string subDir in Directory.GetDirectories(path))
                    {
                        queue.Enqueue(subDir);
                    }
                }
                catch (Exception ex)
                {
                    logger.Debug("===========发生错误啦*========================");
                    logger.Debug(ex.ToString());
                    logger.Debug("===========发生错误了========================");
                }
                string[] files = null;
                try
                {
                    files = Directory.GetFiles(path);
                }
                catch (Exception ex)
                {
                    logger.Debug("===========发生错误啦&========================");
                    logger.Debug(ex.ToString());
                    logger.Debug("===========发生错误了========================");
                }
                if (files != null)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        yield return files[i];
                    }
                }
            }
        }
复制代码
  • 在获取了所有文件之后,上传至指定文档库即可,别忘记处理非法字符。

三、异常处理

主要发生的异常是文件名包含Invalid字符,对SharePoint而言,文档库Folder和File的名字都有严格的限制,不能包含#、%等,现在处理异常是记录到日志然后手动去修改名称

  • 报错的异常

 

  • 将异常记录至日志里,方便修改。

四、检查是否导入成功

  • 导入成功界面

  • 检查日志

  • 登陆系统,检查是否全部导入,并且检查权限设置是否正确。

  • 查看文件夹和文档是否成功创建和上传

 

 

 

 

 

88x31.png
本博客为 木宛城主原创,基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 木宛城主(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。

本文转自木宛城主博客园博客,原文链接:http://www.cnblogs.com/OceanEyes/p/migrate-tfs-to-sharepoint.html,如需转载请自行联系原作者
目录
相关文章
|
11月前
|
JSON 小程序 数据库
小程序批量导入excel数据,云开发数据库导出cvs乱码解决方案
小程序批量导入excel数据,云开发数据库导出cvs乱码解决方案
394 0
|
关系型数据库 Java MySQL
|
数据库
【视频】配置信息管理 的 使用方法(一):数据库文档(Excel)的格式说明
  这个视屏是对数据库文档(Excel)的格式的说明。必须按照这样的格式填写才能被配置信息管理程序所识别。        感谢 svnhost.cn 提供空间,因为园子里只有30M的空间,远远不够用,呵呵。
696 0
|
索引 C#
SharePoint 2016 文档库的新功能简介
  今天,重装了一下SharePoint 2016,想多了解了解,看到一些自己平时没注意的功能,或者新的功能,分享一下给大家。   1、界面上操作的变换,多了一排按钮,更像SharePoint Online了,呵呵;这一排按钮可以新建、上传、同步、共享等操作;   2、共享功能的界面有了新的...
1121 0