将附件从SP迁移到SQL BLOB

时间:2017-08-16 04:47:23

标签: c# sql-server sharepoint ssis sharepoint-2013

我需要将SharePoint中的多个列表中的大量附件移动到SQL中的BLOB表。我找到了允许我将附件下载到本地驱动器的代码,但我还没有能够修改它以将其作为二进制数据直接加载到SharePoint中。

using Microsoft.SharePoint.Client;
using System;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    public override void CreateNewOutputRows()
    {
    try
    {
        int startListID = 1;

        String siteUrl = "https://mysharepointsite.com/sites/mysite";
        String listName = "AttachmentTesting";
        NetworkCredential credentials =
                    new NetworkCredential("username", "password", "domain");

        using (ClientContext clientContext = new ClientContext(siteUrl))
        {
            clientContext.Credentials = credentials;

            //Get the Site Collection
            Site oSite = clientContext.Site;
            clientContext.Load(oSite);
            clientContext.ExecuteQuery();

            // Get the Web
            Web oWeb = clientContext.Web;
            clientContext.Load(oWeb);
            clientContext.ExecuteQuery();

            CamlQuery query = new CamlQuery();
            query.ViewXml = @"";

            List oList = clientContext.Web.Lists.GetByTitle(listName);
            clientContext.Load(oList);
            clientContext.ExecuteQuery();

            ListItemCollection items = oList.GetItems(query);
            clientContext.Load(items);
            clientContext.ExecuteQuery();

            foreach (ListItem listItem in items)
            {
                if (Int32.Parse(listItem["ID"].ToString()) >= startListID)
                {

                    Folder folder =
                          oWeb.GetFolderByServerRelativeUrl(oSite.Url +
                          "/Lists/" + listName + "/Attachments/" +

                          listItem["ID"]);

                    clientContext.Load(folder);

                    try
                    {
                        clientContext.ExecuteQuery();
                    }
                    catch (ServerException ex)
                    {
                    }

                    FileCollection attachments = folder.Files;
                    clientContext.Load(attachments);
                    clientContext.ExecuteQuery();

                    foreach (Microsoft.SharePoint.Client.File oFile in folder.Files)
                    {
                        FileInfo myFileinfo = new FileInfo(oFile.Name);
                        WebClient client1 = new WebClient();
                        client1.Credentials = credentials;

                        byte[] fileContents =
                              client1.DownloadData("https://mysharepointsite.com" +
                              oFile.ServerRelativeUrl);

                    }
                }
            }

        }
    }
    catch (Exception e)
    {
    }
}
}

最后的文件流只是为了测试以前的代码,并成功检索附件。现在我需要采取下一步并将其加载到某种缓冲区以推送到SQL。我尝试过使用:

Output0Buffer.AddRow();
Output0Buffer.fileName = oFile.Name;

在循环内部和Output0Buffer.SetEndOfRowset();结尾但这会产生错误:

[Import Column [2]] Error: SSIS Error Code DTS_E_INDUCEDTRANSFORMFAILUREONERROR.  The "Import Column" failed because error code 0xC02090BB occurred, and the error row disposition on "Import Column.Inputs[Import Column Input].Columns[fileName]" specifies failure on error. An error occurred on the specified object of the specified component.  There may be error messages posted before this with more information about the failure.

如何将我的字节数组fileContents推送到我的SQL表blob列的最后一步? 非常感谢。

编辑:我应该省略fstream。那只是为了测试目的。我想要做的是将附件从SharePoint直接推送到SQL,而无需将其存储在本地的中间步骤。

2 个答案:

答案 0 :(得分:0)

您应该使用本地驱动器的路径。

string path = "C:\\Temp\\" + oFile.Name;
FileStream fStream = new FileStream(path, FileMode.Create);

fStream.Write(fileContents, 0, fileContents.Length);
fStream.Close();

Output0Buffer.AddRow();
Output0Buffer.fileName = path;

// ... after foreach loop
Output0Buffer.SetEndOfRowset();

答案 1 :(得分:0)

解决!

感谢tinamou的回答,但我应该提到我试图避免将文件放在本地驱动器上的中间步骤。

我通过向脚本组件添加另一个输出来解决它,名为" fileBinary",并使用AddBlobData方法用我的字节数组填充它。

byte[] fileContents = client1.DownloadData("https://mysharepointsite.com/sites/mysite" +
                              oFile.ServerRelativeUrl);

Output0Buffer.AddRow();
Output0Buffer.fileName = oFile.Name;
Output0Buffer.fileBinary.AddBlobData(fileContents);

然后在我的所有FOR循环之外(也由tinamou建议):

Output0Buffer.SetEndOfRowset();