SharePoint 2010 – 客户端对象模型 – 向ListItem添加附件

我有一个SharePoint列表,我正在使用客户端对象模型添加新的ListItems。 添加ListItems不是问题,而且效果很好。

现在我想添加附件。

我以下列方式使用SaveBinaryDirect:

File.SaveBinaryDirect(clientCtx, url.AbsolutePath + "/Attachments/31/" + fileName, inputStream, true); 

只要我尝试添加附件的项目已经具有通过SharePoint网站添加的附件而不使用客户端对象模型,它就没有任何问题。

当我尝试将附件添加到没有任何附件的项目时,我会收到以下错误(两者都发生但没有相同的文件 – 但这两个消息始终显示):

 远程服务器返回错误:(409)冲突 
 远程服务器返回错误:(404)Not Found 

我想我可能需要先为这个项目创建附件文件夹。 当我尝试以下代码时:

 clientCtx.Load(ticketList.RootFolder.Folders); clientCtx.ExecuteQuery(); clientCtx.Load(ticketList.RootFolder.Folders[1]); // 1 -> Attachment folder clientCtx.Load(ticketList.RootFolder.Folders[1].Folders); clientCtx.ExecuteQuery(); Folder folder = ticketList.RootFolder.Folders[1].Folders.Add("33"); clientCtx.ExecuteQuery(); 

我收到一条错误消息:

 无法创建文件夹“Lists / Ticket System / Attachment / 33” 

我拥有SharePoint站点/列表的完全管理员权限。

我有什么想法可能做错了吗?

谢谢,Thorben

我和微软讨论了这个问题。 看起来只有一种远程创建附件的方法是List.asmx Web服务。 我也试图创建这个子文件夹,但没有成功。

我也在这个问题上挣扎了很长时间,所以我想我会发布一个完整的代码示例,展示如何成功创建一个列表项并添加一个附件。

我使用Client Object API创建列表项,使用SOAP Web服务添加附件。 这是因为,如在Web上的其他位置所述,客户端对象API仅可用于向项目的上载目录已存在的项目添加附件(例如,如果项目已经具有附件)。 否则它会因409错误而失败。 SOAP Web服务虽然可以解决这个问题。

请注意,我必须克服的另一件事是,即使我使用以下URL添加了SOAP引用:

HTTPS://my.sharepoint.installation/personal/test/_vti_bin/lists.asmx

VS实际添加到app.config的URL是:

HTTPS://my.sharepoint.installation/_vti_bin/lists.asmx

我不得不手动将app.config更改回正确的URL,否则我会收到错误:

列表不存在。 您选择的页面包含一个不存在的列表。 它可能已被其他用户删除。 0x82000006

这是代码:

  void CreateWithAttachment() { const string listName = "MyListName"; // set up our credentials var credentials = new NetworkCredential("username", "password", "domain"); // create a soap client var soapClient = new ListsService.Lists(); soapClient.Credentials = credentials; // create a client context var clientContext = new Microsoft.SharePoint.Client.ClientContext("https://my.sharepoint.installation/personal/test"); clientContext.Credentials = credentials; // create a list item var list = clientContext.Web.Lists.GetByTitle(listName); var itemCreateInfo = new ListItemCreationInformation(); var newItem = list.AddItem(itemCreateInfo); // set its properties newItem["Title"] = "Created from Client API"; newItem["Status"] = "New"; newItem["_Comments"] = "here are some comments!!"; // commit it newItem.Update(); clientContext.ExecuteQuery(); // load back the created item so its ID field is available for use below clientContext.Load(newItem); clientContext.ExecuteQuery(); // use the soap client to add the attachment const string path = @"c:\temp\test.txt"; soapClient.AddAttachment(listName, newItem["ID"].ToString(), Path.GetFileName(path), System.IO.File.ReadAllBytes(path)); } 

希望这有助于某人。

使用Sharepoint 2010,无法使用COM将第一个附件上载到列表项。 建议是使用列表Web服务。

使用Sharepoint 2013,它可以运行。

 AttachmentCreationInformation newAtt = new AttachmentCreationInformation(); newAtt.FileName = "myAttachment.txt"; // create a file stream string fileContent = "This file is was ubloaded by client object meodel "; System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); byte[] buffer = enc.GetBytes(fileContent); newAtt.ContentStream = new MemoryStream(buffer); // att new item or get existing one ListItem itm = list.GetItemById(itemId); ctx.Load(itm); // do not execute query, otherwise a "version conflict" exception is rised, but the file is uploaded // add file to attachment collection newAtt.ContentStream = new MemoryStream(buffer); itm.AttachmentFiles.Add(newAtt); AttachmentCollection attachments = itm.AttachmentFiles; ctx.Load(attachments); ctx.ExecuteQuery(); // see all attachments for list item // this snippet works if the list item has no attachments 

此方法用于http://www.mailtosharepoint.net/

它在Microsoft SharePoint团队中反映得相当糟糕,因为没有提出对该问题的确认以及如何解决该问题的可用建议。 以下是我处理它的方式:

我正在使用产品附带的新SharePoint 2010托管客户端。 因此,我已经有一个带有凭据的SharePoint ClientContext。 以下函数将附件添加到列表项:

 private void SharePoint2010AddAttachment(ClientContext ctx, string listName, string itemId, string fileName, byte[] fileContent) { var listsSvc = new sp2010.Lists(); listsSvc.Credentials = _sharePointCtx.Credentials; listsSvc.Url = _sharePointCtx.Web.Context.Url + "_vti_bin/Lists.asmx"; listsSvc.AddAttachment(listName, itemId, fileName, fileContent); } 

上面代码的唯一先决条件是添加到项目(我使用Visual Studio 2008)_web_reference_我称为sp2010,它是从以下URL创建的:http:// /_vti_bin/Lists.asmx

好的机会…

我在我的COM应用程序中使用并尝试过这个,它对我有用

 using (ClientContext context = new ClientContext("http://spsite2010")) { context.Credentials = new NetworkCredential("admin", "password"); Web oWeb = context.Web; List list = context.Web.Lists.GetByTitle("Tasks"); CamlQuery query = new CamlQuery(); query.ViewXml = "New Task Created"; ListItemCollection listItems = list.GetItems(query); context.Load(listItems); context.ExecuteQuery(); FileStream oFileStream = new FileStream(@"C:\\sample.txt", FileMode.Open); string attachmentpath = "/Lists/Tasks/Attachments/" + listItems[listItems.Count - 1].Id + "/sample.txt"; Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, attachmentpath, oFileStream, true); } 

注意:仅在已创建项目文件夹时有效

HTML:

  

代码背后的事件:

 protected void UploadMultipleFiles(object sender, EventArgs e) { Common.UploadDocuments(Common.getContext(new Uri(Request.QueryString["SPHostUrl"]), Request.LogonUserIdentity), FileUpload1.PostedFiles, new CustomerRequirement(), 5); } public static List UploadDocuments(ClientContext ctx,IList selectedFiles, T reqObj, int itemID) { List existingFiles = null; List processedFiles = null; List unProcessedFiles = null; ListItem item = null; FileStream sr = null; AttachmentCollection attachments = null; byte[] contents = null; try { existingFiles = new List(); processedFiles = new List(); unProcessedFiles = new List(); //Get the existing item item = ctx.Web.Lists.GetByTitle(typeof(T).Name).GetItemById(itemID); //get the Existing attached attachments attachments = item.AttachmentFiles; ctx.Load(attachments); ctx.ExecuteQuery(); //adding into the new List foreach (Attachment att in attachments) existingFiles.Add(att); //For each Files which user has selected foreach (HttpPostedFile postedFile in selectedFiles) { string fileName = Path.GetFileName(postedFile.FileName); //If selected file not exist in existing item attachment if (!existingFiles.Any(x => x.FileName == fileName)) { //Added to Process List processedFiles.Add(postedFile.FileName); } else unProcessedFiles.Add(fileName); } //Foreach process item add it as an attachment foreach (string path in processedFiles) { sr = new FileStream(path, FileMode.Open); contents = new byte[sr.Length]; sr.Read(contents, 0, (int)sr.Length); var attInfo = new AttachmentCreationInformation(); attInfo.FileName = Path.GetFileName(path); attInfo.ContentStream = sr; item.AttachmentFiles.Add(attInfo); item.Update(); } ctx.ExecuteQuery(); } catch (Exception ex) { throw ex; } finally { existingFiles = null; processedFiles = null; item = null; sr = null; attachments = null; contents = null; ctx = null; } return unProcessedFiles; }