4

I am looking for code that will 100% duplicate a file including all historical versions, dates of versions, comments and anything else. My test code is showing that capturing all those details is a very difficult thing to do because both the source and destination libraries have to be configured the same (i.e. version major/minor versions, approvals)

The code will be used in an custom action or workflow.

The purpose of this is for archiving documents while maintaining historical changes for auditing and regulatory compliance.

Thank you!

2 Answers 2

1

You can use this function created by Julie Turner. Function takes two parameters SPListItem itmSource which is the source item to move, and SPDocumentLibrary libDest which is the target document library.

SPFile fileSource = itmSource.File;
/*Here we'll get the created by and created on values from the source document.*/
SPUser userCreatedBy = fileSource.Author;
/*Note we need to convert the "TimeCreated" property to local time as it's stored in the database as GMT.*/
DateTime dateCreatedOn = fileSource.TimeCreated.ToLocalTime();
//Get the versions
int countVersions = itmSource.File.Versions.Count;
/*This is a zero based array and so normally you'd use the < not <= but we need to get the current version too which is not in the SPFileVersionCollection so we're going to count one higher to accomplish that.*/
for (int i = 0; i <= countVersions; i++)
{
     Hashtable hashSourceProp;
     Stream streamFile;
     SPUser userModifiedBy;
     DateTime dateModifiedOn;
     string strVerComment = "";
     bool bolMajorVer = false;
     if (i < countVersions)
     {
/*This section captures all the versions of the document and gathers the properties we need to add to the SPFileCollection.  Note we're getting the modified information and the comments seperately as well as checking if the version is a major version (more on that later).  I'm also getting a stream object to the file which is more efficient than getting a byte array for large files but you could obviously do that as well.  Again note I'm converting the created time to local time.*/
          SPFileVersion fileSourceVer = itmSource.File.Versions[i];
          hashSourceProp = fileSourceVer.Properties;
          userModifiedBy = (i == 0) ? userCreatedBy: fileSourceVer.CreatedBy;
          dateModifiedOn = fileSourceVer.Created.ToLocalTime();
          strVerComment = fileSourceVer.CheckInComment;
          bolMajorVer = fileSourceVer.VersionLabel.EndsWith("0") ? true : false;
          streamFile = fileSourceVer.OpenBinaryStream();
     }
     else
     {
/*Here I'm getting the information for the current version.  Unlike in SPFileVersion when I get the modified date from SPFile it's already in local time.*/
          userModifiedBy = fileSource.ModifiedBy;
          dateModifiedOn = fileSource.TimeLastModified;
          hashSourceProp = fileSource.Properties;
          strVerComment = fileSource.CheckInComment;
          bolMajorVer = fileSource.MinorVersion == 0 ? true : false;
          streamFile = fileSource.OpenBinaryStream();
     }
     string urlDestFile = libDest.RootFolder.Url + "/" + fileSource.Name;
/*Here I'm using the overloaded Add method to add the file to the SPFileCollection.  Even though this overload takes the created and modified dates for some reason they aren't visible in the SharePoint UI version history which shows the date/time the file was added instead, however if this were a Microsoft Word document and I opened it in Word 2010 and looked at the version history it would all be reflective of the values passed to this Add method.  I'm voting for defect but there could just be something I'm missing.*/
     SPFile fileDest = libDest.RootFolder.Files.Add(
                 urlDestFile, 
                 streamFile, 
                 hashSourceProp, 
                 userCreatedBy, 
                 userModifiedBy, 
                 dateCreatedOn, 
                 dateModifiedOn, 
                 strVerComment, 
                 true);
     if (bolMajorVer)
/*Here we're checking if this is a major version and calling the publish method, passing in the check-in comments.  Oddly when the publish method is called the passed created and modified dates are displayed in the SharePoint UI properly without further adjustment.*/
          fileDest.Publish(strVerComment);
     else
     {
/*Setting the created and modified dates in the SPListItem which corrects the display in the SharePoint UI version history for the draft versions.*/
          SPListItem itmNewVersion = fileDest.Item;
          itmNewVersion["Created"] = dateCreatedOn;
          itmNewVersion["Modified"] = dateModifiedOn;
          itmNewVersion.UpdateOverwriteVersion();
     }
}

Link to source

1
  • This is a great start and the exact same code I am working with. It has some deficiencies though. Most notably it is missing handling for ModerationInformation.
    – ChiliYago
    Commented Jan 10, 2014 at 16:14
1

Using this one we can move file with including of version history from one site collection to another site or site collection or another web application.

/*Change Parameters.*/
string sourceSiteUrl = "http://contoso:100/doccntr/Docs/";
string destSiteUrl = "http://contoso:100/sites/Archive/";
string srcUrl = "http://contoso:100/doccntr/Docs/Design%20history.txt";    
            using (SPSite siteSrc = new SPSite(sourceSiteUrl))
            using (SPSite siteDst = new SPSite(destSiteUrl))
            using (SPWeb webSrc = siteSrc.OpenWeb())
            using (SPWeb webDst = siteDst.OpenWeb())
            {

                SPFile fileSource = webSrc.GetFile(srcUrl);   //itmSource.File;

                //Get destination Lib instance
                SPList libDest = webDst.Lists[fileSource.Item.ParentList.Title];

                /*Here we'll get the created by and created on values from the source document.*/
                SPUser userCreatedBy = fileSource.Author;
                SPUser userModifiedBy = fileSource.ModifiedBy;
                /*Note we need to convert the "TimeCreated" property to local time as it's stored in the database as GMT.*/
                DateTime dateCreatedOn = fileSource.TimeCreated.ToLocalTime();
                //Get the versions
                int countVersions = fileSource.Versions.Count;
                /*This is a zero based array and so normally you'd use the < not <= but we need to get the current version too which is not in the SPFileVersionCollection so we're going to count one higher to accomplish that.*/
                for (int i = 0; i <= countVersions; i++)
                {
                    Console.Write("Item Vesrion no :  " + i);
                    Hashtable hashSourceProp;
                    Stream streamFile;
                    //SPUser userModifiedBy;
                    DateTime dateModifiedOn;
                    string strVerComment = "";
                    bool bolMajorVer = false;
                    if (i < countVersions)
                    {
                        /*This section captures all the versions of the document and gathers the properties we need to add to the SPFileCollection.  Note we're getting the modified information and the comments seperately as well as checking if the version is a major version (more on that later).  I'm also getting a stream object to the file which is more efficient than getting a byte array for large files but you could obviously do that as well.  Again note I'm converting the created time to local time.*/
                        SPFileVersion fileSourceVer = fileSource.Versions[i];
                        hashSourceProp = fileSourceVer.Properties;
                        userModifiedBy = (i == 0) ? userCreatedBy : fileSource.Author;
                        dateModifiedOn = fileSourceVer.Created.ToLocalTime();
                        strVerComment = fileSourceVer.CheckInComment;
                        bolMajorVer = fileSourceVer.VersionLabel.EndsWith(".0") ? true : false;
                        streamFile = fileSourceVer.OpenBinaryStream();
                    }
                    else
                    {
                        /*Here I'm getting the information for the current version.  Unlike in SPFileVersion when I get the modified date from SPFile it's already in local time.*/
                        userModifiedBy = fileSource.ModifiedBy;
                        dateModifiedOn = fileSource.TimeLastModified;
                        hashSourceProp = fileSource.Properties;
                        strVerComment = fileSource.CheckInComment;
                        bolMajorVer = fileSource.MinorVersion == 0 ? true : false;
                        streamFile = fileSource.OpenBinaryStream();
                    }
                    string urlDestFile = fileSource.Url.ToString();
                    /*Here I'm using the overloaded Add method to add the file to the SPFileCollection.  Even though this overload takes the created and modified dates for some reason they aren't visible in the SharePoint UI version history which shows the date/time the file was added instead, however if this were a Microsoft Word document and I opened it in Word 2010 and looked at the version history it would all be reflective of the values passed to this Add method.  I'm voting for defect but there could just be something I'm missing.*/
                    SPFile fileDest = libDest.RootFolder.Files.Add(
                                urlDestFile,
                                streamFile,
                                hashSourceProp,
                                libDest.ParentWeb.EnsureUser(userCreatedBy.LoginName),
                                libDest.ParentWeb.EnsureUser(userModifiedBy.LoginName),
                                dateCreatedOn,
                                dateModifiedOn,
                                strVerComment,
                                true);
                    if (bolMajorVer)
                    {
                        /*Here we're checking if this is a major version and calling the publish method, passing in the check-in comments.  Oddly when the publish method is called the passed created and modified dates are displayed in the SharePoint UI properly without further adjustment.*/
                        fileDest.Publish(strVerComment);
                        fileDest.Approve(strVerComment); ;
                    }
                    else
                    {
                        /*Setting the created and modified dates in the SPListItem which corrects the display in the SharePoint UI version history for the draft versions.*/
                        SPListItem itmNewVersion = fileDest.Item;
                        itmNewVersion["Created"] = dateCreatedOn;
                        itmNewVersion["Modified"] = dateModifiedOn;
                        itmNewVersion.UpdateOverwriteVersion();
                    }
                }

            }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.