Using the Object Model, adding items to a SharePoint document library is easy enough, given the code below you can add a new document library item and set it’s meta data at the same time.
var metadata = new Hashtable { {"vti_title", "some document title"} }; var documentFile = list.RootFolder.Files.Add("mydoc.docx", documentBytes, metadata, true);
But, how to update a doucment library item? Well given the same document url (LinkFilename) you can just call the above code again, assuming you set the last (bool) parameter to true, to overwrite any existing file.
There is another way to update just the document file of a document library item, and that is to use SPFile.SaveBinary().
using (var site = new SPSite(<a href="http://portal">http://portal</a>)) using (var web = site.OpenWeb()) { SPFile file = web.GetFolder("Documents").Files["mydoc.docx"]; using (var fs = new FileInfo(@"E:\Documents\mydoc.docx").OpenRead()) { documentBytes = ..... // get the documents bytes } file.SaveBinary(documentBytes); }
Using this technique you can update just the document file part of a document library item.
This works out great, except when it doesn’t………….well not always.
When you’re dealing with non-Office documents, with or without content types, it does work out just fine. You get the expected results every time.
When you’re dealing with Office documents, SharePoints automatic document property promotion steps in with it’s size 12 boots and kicks you in the shins!
If you call the above code you’ll find that your document library item has been set to the default content type (if you’re using content types) and all your custom field settings have been wiped (or at least set to their defaults), and this is due to the way SharePoint property promotion works with Office documents in order for it to keep document properties in synch with SharePoint list item properties.
If this is a problem for you (i.e you want to programmatically manage SharePoint properties), one possible workaround is to create an event handler to handle the checkin/checkout events and set the item field values to the old field values during checkin, as described in this post.
Another solution involves setting the SPWeb.ParserEnabled property as shown;
using (var site = new SPSite("http://portal")) using (var web = site.OpenWeb()) { SPFile file = web.GetFolder("Documents").Files["mydoc.docx"]; using (var fs = new FileInfo(@"E:\Documents\mydoc.docx").OpenRead()) { documentBytes = ..... // get the documents bytes } web.ParserEnabled = false; web.Update(); file.SaveBinary(documentBytes); web.ParserEnabled = true; web.Update(); }
This has the effect of temporarily disabling automatic document property promotion, obviously you probably don’t want to turn it off permanently since this feature plays an important part of Search – the ability for Office document properties to be surfaced within SharePoint and therefore to be searchable.
very good, thx for your share.
Many thanks for sharing your fantastic website.