Skip to main content

Replace attachment in document library without changing version number

·2 mins

Lately I was looking for some example on how to replace the attachment in document library (SP2010) without changing the version number but without any results. If you’ve faced the same problem here is the solution:

SPWeb webSite = SPContext.Current.Web;  
SPDocumentLibrary library = webSite.Lists[libraryName] as SPDocumentLibrary;  

if (library == null)  
{  
    throw new SPException("There is no document library named " + libraryName);  
}  

using (MemoryStream docStream = new MemoryStream())  
{  
    BinaryWriter docWriter = new BinaryWriter(docStream);  
    docWriter.Write(yourContentString);  

    SPFile file = find(library, fileName);  

    if (file == null)  
    {  
        throw new SPException("File " + fileName + " not found");  
    }  

    file.CheckOut();  
    file.SaveBinary(docStream);  
    file.CheckIn(string.Empty, SPCheckinType.OverwriteCheckIn);  

    docWriter.Close();  
}  

Utility method find() - find a file by name - is defined as follow:

private static SPFile find(SPDocumentLibrary library, string fileName)  
{  
    SPFileCollection files = library.RootFolder.Files;  
    for (int fileIdx = 0; fileIdx < files.Count; fileIdx++)  
    {  
        if (files[fileIdx].Name == fileName)  
        {  
            return files[fileIdx];  
        }  
    }  

    return null;  
}  

Im assuming that the file has already been uploaded to document library. The most important parts are:

  1. Retrieve reference to the file (SPFile). I’ve done this by iterating through all files in root folder of document library, but actually you can do this however you want
  2. Check out the file (SPFile.CheckOut()):
file.CheckOut();
  1. Replace the attachment. Convenient method for doing this is SPFile.SaveBinary which takes stream with content as an argument (I’ve used MemoryStream to read the content from a text box in my PoC, but you can pass the FileStream or something else):
file.SaveBinary(docStream);
  1. Check-in the file (SPFile.CheckIn()). In order to save the attachment without increasing the version number you must specify SPCheckinType as OverwriteCheckIn
    file.CheckIn(string.Empty, SPCheckinType.OverwriteCheckIn);  

The alternative method is by using SPListItem.SystemUpdate with incrementListItemVersion set false. SystemUpdate will not change item modification date and modified by fields values. In this approach you will work with document library item instead of file.
Additionally if you want to change the attachment name, you can do this by with SPFile.MoveTo method (after changing the original attachment content):

if (!string.IsNullOrEmpty(newFileName))  
{  
    string newPath = string.Format("{0}/{1}", file.ParentFolder.Url, newFileName);  
    file.MoveTo(newPath, true);  
}  

The VS solution with code samples for this article is available on GitHub

Happy SharePointing!

A notice for archeologists...🏺 This post was originaly published on my previous blog and moved here. Some links and resources might not be up to date.