Posted on:
Categories: Office 365;SharePoint
Description:

​I’m currently working on a provider hosted SharePoint Add-in for a client and I ran into an issue creating list item attachments through our custom code. This issue was related to attaching large files as attachments to the list item via CSOM. The issue I encountered was that if it was a large file I needed to attach I needed to have the attachments folder already created before I could upload the large files.

I created something similar to the large file upload solution that is posted in the Office Dev Patterns and Practices samples (https://github.com/OfficeDev/PnP/tree/master/Samples/Core.LargeFileUpload). This enables you to add files larger than 2 MB in pieces (Option 3). Using this method requires that the attachments folder for the list item already exists, if not it will fail and throw an error.

After trying a few ways of creating a folder for the list item, such as getting the list and trying to add a folder directly via CSOM which throws an error. I did some research and found some workarounds using the lists.asmx web service to create the folders. Since the older web services are going to be phased out in favour of the newer REST services I decided that wasn’t the best option for a long term solution.

Since the issue was only related to adding large files, I decided that adding a small temporary file as an attachment first. This would then create the folder for me, and then I could delete the temporary file and move onto uploading my large attachment.

//get the list item and the list's root folder with subfolders
var list = clientContext.Web.Lists.GetByTitle(listName);
var item = list.GetItemById(listItemId);
clientContext.Load(item); 
clientContext.Load(list.RootFolder.Folders);
clientContext.ExecuteQuery();
//get the attachments folder for the list
var rootFolder = Enumerable.FirstOrDefault(list.RootFolder.Folders, folder => folder.Name == "Attachments");
clientContext.Load(rootFolder, rf => rf.Folders);
clientContext.ExecuteQuery();
var attachmentFolder = Enumerable.FirstOrDefault(rootFolder.Folders, folder => folder.Name == listItemId.ToString());
// if the list item doesn't have an subfolder under the attachments folder, then add a temp file to create the folder
if (attachmentFolder == null)
{
 //create dummy attachment to force creation of the attachment folder for the list item
 //note: this is needed due to limitations in CSOM and creating folders
 using (
 var dummyFileStream =
 new FileStream(HostingEnvironment.MapPath(“path to dummy file”),
FileMode.Open))
 {
 var fileInfo = new AttachmentCreationInformation
 {
 ContentStream = dummyFileStream,
 FileName = "tempfile.txt"
 };
 var tempUploadFile = item.AttachmentFiles.Add(fileInfo);
 clientContext.Load(tempUploadFile);
 clientContext.ExecuteQuery();
 //delete temp file
 tempUploadFile.DeleteObject();
 clientContext.ExecuteQuery();
 }
}

At this point the folder for the item’s attachments is now created, and I can proceed to upload the large attachment.