SharePoint 2010 - клиентская объектная модель-добавление вложения в ListItem
У меня есть список SharePoint, в который я добавляю новые ListItems, используя клиентскую объектную модель.
Добавление ListItems не является проблемой и отлично работает.
Теперь я хочу добавить вложения.
Я использую SaveBinaryDirect следующим образом:
File.SaveBinaryDirect(clientCtx, url.AbsolutePath + "/Attachments/31/" + fileName, inputStream, true);
Это работает без каких-либо проблем, пока элемент, к которому я пытаюсь добавить вложение, уже имеет вложение, добавленное через сайт SharePoint и не использующее клиентскую объектную модель.
Когда Я попробуйте добавить вложение к элементу, который еще не имеет вложений, я получу следующие ошибки (оба случаются, но не с теми же файлами - но эти два сообщения появляются последовательно):
The remote server returned an error: (409) Conflict
The remote server returned an error: (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();
Я получаю сообщение об ошибке, говорящее::
Cannot create folder "Lists/Ticket System/Attachment/33"
У меня есть полные права администратора для сайта/списка SharePoint.
Любые идеи, что я может, я делаю что-то не так?
Спасибо, Торбен
6 ответов:
Я обсуждал этот вопрос с Microsoft. Похоже, что только один способ создать вложения удаленно-Это список.служба ASMX. Я также пытался создать эту подпапку, но безуспешно.
Я долго боролся с этой проблемой, поэтому решил опубликовать полный пример кода, показывающий, как успешно создать элемент списка и добавить вложение.
Я использую API объекта клиента для создания элемента списка и веб-службу SOAP для добавления вложения. Это связано с тем, что, как отмечалось в других местах в интернете, API объекта клиента можно использовать только для добавления вложений к элементу, где каталог загрузки элемента уже существует (например. если элемент уже имеет привязанность). В противном случае он терпит неудачу с ошибкой 409 или что-то в этом роде. Однако веб-служба SOAP справляется с этим нормально.
Обратите внимание, что еще одна вещь, которую я должен был преодолеть, заключалась в том, что, хотя я добавил ссылку SOAP, используя следующий URL:
Https://my.служба SharePoint.установка / персональный / тест/_vti_bin / списки.asmx
URL, который VS фактически добавил в приложение.конфиг:
Https://my.служба SharePoint.установка/_vti_bin / списков.asmx
Мне пришлось вручную изменить приложение.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. Было рекомендовано использовать веб-сервис списков inmstead.
С 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 с учетными данными. Следующая функция добавляет вложение к элементу списка:
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 сопоставляется/списки.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 = "<View><Where><Eq><FieldRef Name = \"Title\"/><Value Type=\"String\">New Task Created</Value></Eq></Where></View>"; 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); }Примечание: работает только в том случае, если папка item уже создана
HTML:
<asp:FileUpload ID="FileUpload1" runat="server" AllowMultiple="true" />Событие в коде позади:
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<string> UploadDocuments<T>(ClientContext ctx,IList<HttpPostedFile> selectedFiles, T reqObj, int itemID) { List<Attachment> existingFiles = null; List<string> processedFiles = null; List<string> unProcessedFiles = null; ListItem item = null; FileStream sr = null; AttachmentCollection attachments = null; byte[] contents = null; try { existingFiles = new List<Attachment>(); processedFiles = new List<string>(); unProcessedFiles = new List<string>(); //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; }
Comments