我有一个SharePoint List,我正在使用客户端对象模型添加新的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网站/列表的完全管理员权限。
任何想法我可能做错了什么?
谢谢,Thorben
答案 0 :(得分:12)
我也在这个问题上挣扎了很长时间,所以我想我会发布一个完整的代码示例,展示如何成功创建列表项并添加附件。
我使用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是:
我不得不手动将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));
}
希望这有助于某人。
答案 1 :(得分:9)
我与微软讨论了这个问题。看起来只有一种远程创建附件的方法是List.asmx Web服务。我也试图创建这个子文件夹但没有成功。
答案 2 :(得分:6)
使用Sharepoint 2010,无法使用COM将第一个附件上传到列表项。建议是使用列表网络服务。
使用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
答案 3 :(得分:4)
在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
Bon Chance ......
答案 4 :(得分:0)
我已经在我的CSOM(SharePoint客户端对象模型)应用程序中使用并尝试了这个,它适用于我
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);
}
注意:仅在已创建项目文件夹时才有效
答案 5 :(得分:0)
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;
}