Tuesday, November 25, 2008

How to copy attachments from one list item to another

The microsoft support article for WSS 2 shows us how to download attachments from a list item. Basically, the attachments for a list item are stored as SPFile objects under a hidden folder in the list where those attachments are (a folder called "Attachments") - where each list item that has an attachment has its own folder - with the ID of the item being the folder's name. Here is a code sample for a function to copy attachments from one item to another.

private void CopyAttachments(SPListItem sourceItem, SPListItem targetItem)
{
  try
  {
     //get the folder with the attachments for the source item
     SPFolder sourceItemAttachmentsFolder =
         sourceItem.Web.Folders["Lists"].SubFolders[sourceItem.ParentList.Title].SubFolders["Attachments"].SubFolders[sourceItem.ID.ToString()];
      //Loop over the attachments, and add them to the target item
     foreach (SPFile file in sourceItemAttachmentsFolder.Files)
     {
        byte[] binFile = file.OpenBinary();
        targetItem.Attachments.AddNow(file.Name, binFile);
     }
  }
  catch { }
  finally
  {
     sourceItem.Web.Dispose();
  }
}

4 comments:

Tahir said...

Thankyou so much, Sagi.

sp2kxn said...

thanx !

Lars Nielsen said...

Thanks for this - these code snippets are so helpful! I used this for a utility I have written that replicates a list on a different site. A couple of things to mention:

1) I don't think you need the sourceItem.Web.Dispose(); in the finally clause? The method doesn't create a new SPWeb object? I would replace that line with sourceItem.Web.Update();

2)
The AddNow() method throws an SPException if the attachment is already present in the target. The catch { } clause swallows up this exception so no exception is thrown, but if you want to log cases of duplcuite attachments during the copy process, you can log it in the catch {} block.

3) If you use this method as part of code to update the targetItem itself, you need to call Update() on targetItem BEFORE calling CopyAttachments(), not afterwards.

Sandeep K Nahta said...

I think its better to use listItem.Attachments to get SPAttachmentCollection to make sure you handle multiple attchment scenario.

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splistitem.attachments.aspx


Thanks