Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Uploading files to the SharePoint Document Library and updating any metadata columns

4.41/5 (17 votes)
10 Jun 2008CPOL4 min read 2   2.5K  
How to upload files to the SharePoint Document Library and update any metadata columns.

Introduction

This article describes uploading files in a sequence to a SharePoint Document Library and then using CAML for updating each file's custom meta data. This article also describes how to use the DWS Web Service to create folders/subfolders in a Doc Lib and how to use the List Web Service to upload/update files inside a Doc Lib.

Background

In my organization, a large number of documents are scanned each day (.pdf), and we maintain a complex electronic system of approving documents and filtering/searching based on the respective metadata. Files are named in a specific manner. I had to write a Web Service named File Shunter in VB.NET which contains two functions: a function that takes the input folder and uploads the files to a server into a specific folder (this function also creates folders/subfolders based on the rules in the file name using the SharePoint DWS Web service), and another function for each document being uploaded, that extracts all the required metadata from the file name, and once the file has been uploaded, uses CAML and the List Web service (http://sp portal/subsite/_vti_bin/lists.asmx) to update the required metadata columns for the file. I use Web.config to store/retrieve the doc library name, portal name, user authentication etc... This code uses web services, so it is not required to run the code on the server where the portal is running (in cases where the SharePoint Object Model is used).

Another feature is we have to maintain the version history of each file. Since a file can be uploaded multiple times, we need to keep revisions. For this purpose, if version history is enabled in the document library and if a file's metadata is changed after it has been uploaded, it will become a new version. While we need to access and update the current file without making another version while updating it for this purpose, the function bEnableVersion(True/False) is used, which is set to True when uploading the file so that if the file already exists, then a version is generated inside the Doc Lib. But when updating its metadata, version history is set to false (bEnableVersion(False)). Another good feature of a document library is that it can be used as a mapped drive inside a file system (since it's a web folder). Our documentation dept. was used to accessing files from a shared folder before. Now, after files are uploaded to SharePoint, we just map the document library as a shared folder for each user so there is no difference for them to work/access these files. Just enable the WebClient service on the user's PC and map the Doc Lib (http://portal/site/doclib).

Using the code

There are two main functions: UploadDocument and WSSUpdateFile. The first function is passed the local file name (on the file system) and the remote file name (to be used inside the Doc Lib). Once the file is uploaded, the other function is passed the file name and any metadata column values to be updated. For test purposes, I created a column named "TestCol" in my test document library and passed it "Test Value". But this function can be passed as many number of metadata column values as required. Just add them in the XML batch inside the function with the column name and the value. To update file properties, normally, its ID is required to access it (even inside folders). I have used CAML to access the recently uploaded file and to get its ID, and then this ID is used in the List Web Service UpdateListItems function to update the properties of the file.

Included is the function "CreateFolder" which can be used to create any number of folder/subfolders within a Doc Lib. Most of the common required values like portal URL, Doc Lib name, user, password, domain, folder name (where files reside to be uploaded) are set into Web.config for easy modifications. The main function accesses these values to determine the required data and authentication. To upload the files, let's say from the D:\Test folder, in web.config, under the globalsharedpath key, add "<add key="GlobalSharedPath" value="D:\"/>". Pass only "D:\" and once the program is running, pass only "Test" in the input folder name. One thing to remember is that some of the SharePoint Web Services are site specific, which means you need to reference the exact site/subsite to play with it. For example, if I have a subsite under http://portal/sitedirectory/site, then the List Web Service reference should be like http://portal/sitedirectory/site/_vti_bin/lists.asmx.

Web.config
XML
<configuration>
  <appSettings>
    <add key="SharePointServer" value=http://SP Portal/Site/>
    <add key="DocLibrary" value="Doclib"/>
    <add key="User" value="User"/>
    <add key="Domain" value="Domain"/>
    <add key="Pwd" value="Pwd"/>
    <add key="GlobalSharedPath" value="D:\"/>
  </appSettings>
The code:
VB
Public Function UploadDocument(ByVal localFile As String, _
                ByVal remoteFile As String) As String
    '// Read in the local file
    On Error GoTo handler
    Dim r As Byte()
    Dim Strm As System.IO.FileStream = New System.IO.FileStream(localFile, _
                System.IO.FileMode.Open, System.IO.FileAccess.Read)
    Dim reader As System.IO.BinaryReader = New System.IO.BinaryReader(Strm)
    Dim filecontents As Byte() = reader.ReadBytes(CInt(Strm.Length))
    reader.Close()
    Strm.Close()
    Dim sSPURL As String = ConfigurationManager.AppSettings("SharePointServer")
    Dim sDocLib As String = ConfigurationManager.AppSettings("DocLibrary")
    Dim sUser As String = ConfigurationManager.AppSettings("User")
    Dim sPwd As String = ConfigurationManager.AppSettings("Pwd")
    Dim sDomain As String = ConfigurationManager.AppSettings("Domain")
    Dim sRemoteFileURL As String
    Dim NC As System.Net.NetworkCredential = _
        New System.Net.NetworkCredential(sUser, sPwd, sDomain)
    sRemoteFileURL = sSPURL & "/" & sDocLib & _
                     "/" & Trim(LTrim(RTrim(remoteFile)))
   
    sRemoteFileURL = Replace(sRemoteFileURL, " ", "%20")
    sRemoteFileURL = Replace(sRemoteFileURL, "\", "/")
    Dim m_WC As WebClient = New WebClient
    m_WC.Credentials = NC
    r = m_WC.UploadData(sRemoteFileURL, "PUT", filecontents)
    Return "TRUE"
    Exit Function
handler:
    Return Err.Description
End Function

Public Function WSSUpdateFile(ByVal sFileName As String, ByVal sSiteDoc As String, _
                              ByVal sTestCol As String) As String
    Dim sUser As String = ConfigurationManager.AppSettings("User")
    Dim sPwd As String = ConfigurationManager.AppSettings("Pwd")
    Dim sDomain As String = ConfigurationManager.AppSettings("Domain")
    Dim sFileIDinList As String
    Dim strBatch As String = ""
    sSiteDoc = Replace(sSiteDoc, "%20", " ")
    sSiteDoc = Replace(sSiteDoc, "\", "/")
    Dim sFinalFilePath As String
    Dim sSPURL As String = ConfigurationManager.AppSettings("SharePointServer")
    Dim sDocLib As String = ConfigurationManager.AppSettings("DocLibrary")
    Try
        Dim netAccess As System.Net.NetworkCredential = _
            New System.Net.NetworkCredential(sUser, sPwd, sDomain)
        Dim listService As New SPLists.Lists
        listService.Url = sSPURL & "/_vti_bin/lists.asmx"
        listService.Credentials = netAccess
        sFileIDinList = sGetID(listService.Url, sDocLib, sFileName)
        If sFileIDinList <> "" Then
            sFinalFilePath = sSPURL & "/" & sDocLib & "/" & sFileName
            'Now we have FileID so update the list
            strBatch = "<Method ID='1' Cmd='Update'>" + _
                "<Field Name = 'ID'>" & sFileIDinList & "</Field>" + _
                "<Field Name = 'FileRef'>" & sFinalFilePath & "</Field>" + _
                "<Field Name = 'TestCol'>" & sTestCol & "</Field>" + _
                "</Method>"
            Dim xmlDoc = New System.Xml.XmlDocument
            Dim elBatch As System.Xml.XmlElement = xmlDoc.createelement("Batch")
            elBatch.InnerXml = strBatch
            Dim ndreturn As System.Xml.XmlNode = _
                listService.UpdateListItems(sDocLib, elBatch)
        End If
        Return "TRUE"
    Catch ex As Exception
        Return ex.Message
    End Try
End Function

Private Function sGetID(ByVal sURL As String, ByVal sListGUID As String, _
                 ByVal sFileName As String) As String
    Dim sUser As String = ConfigurationManager.AppSettings("User")
    Dim sPwd As String = ConfigurationManager.AppSettings("Pwd")
    Dim sDomain As String = ConfigurationManager.AppSettings("Domain")
    Dim netAccess As System.Net.NetworkCredential = _
        New System.Net.NetworkCredential(sUser, sPwd, sDomain)
    Dim L As New SPLists.Lists
    L.Credentials = netAccess
    L.Url = sURL
    Dim xmldoc As XmlDocument = New XmlDocument
    Dim query As XmlNode = xmldoc.CreateNode(XmlNodeType.Element, "Query", "")
    query.InnerXml = "<OrderBy><FieldRef Name='Modified' " & _ 
                     "Ascending='False'></FieldRef></OrderBy>"""
    Try
        Dim caml As XmlNode = L.GetListItems(sListGUID, Nothing, query, _
                                             Nothing, "1", Nothing)
        Dim id As String = caml.ChildNodes(1).ChildNodes(1).Attributes("ows_ID").Value
        Return id
    Catch ex As Exception
        Return ex.Message
    End Try
End Function

Points of Interest

  • Using Web Services instead of OM
  • Creating folders inside Doc Lib
  • Enabling/disabling version history

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)