Quantcast
Channel: The Chris Kent » WebClient
Viewing all articles
Browse latest Browse all 2

Using SharePoint RPC to Upload Documents

$
0
0
Applies To: SharePoint, VB.NET

In my last post, Using SharePoint RPC to Create Directories, I showed you the basics of using the SharePoint Foundation RPC Protocol. I provided a lot of the plumbing code needed for executing RPC methods and then demonstrated creating multiple directories in a single call.

In this post, I’ll be building on my SPUploader module to show you how to upload documents while setting the metadata all in a single call. You will need all the code in the first post to make this work.

Uploading Documents

Our goal is to upload a document to a library and set its metadata at the same time using the put document RPC method. There are some additional complications with Office docs that I won’t be addressing, but this should get you started for most file types.

The put document method has four parameters we care about: document, put_option, comment, and keep_checked_out.

Document Details

The document parameter is where you will specify the document name and all meta data. For a document named SomeStuff.csv with a title of “Some Stuff” to be uploaded in the Stuff folder of our Junk library the document parameter needs to look like this:

document=[document_name=Junk/Stuff/SomeStuff.csv;meta_info=[vti_title;SW|Some Stuff]]

Here are some utility functions that will help you generate all the information correctly:

    Private Function documentDetailString(fileName As String, properties As Dictionary(Of String, Object)) As String
        Return String.Format("[document_name={0};meta_info=[{1}]]", EncodeString(fileName), EncodeString(propertiesToString(properties)))
    End Function

    Private Function propertiesToString(properties As Dictionary(Of String, Object)) As String
        If properties Is Nothing Then Return String.Empty
        Dim props As New StringBuilder
        For Each kvp As KeyValuePair(Of String, Object) In properties
            If kvp.Value IsNot Nothing Then
                Dim field As String = kvp.Key
                If field = "Title" Then field = "vti_title"

                Dim value As String
                Dim typeCode As String = "S"
                Select Case (kvp.Value.GetType().FullName)
                    Case "System.Boolean"
                        typeCode = "B"
                        value = IIf(CType(kvp.Value, Boolean), "true", "false")
                    Case "System.DateTime"
                        value = CType(kvp.Value, DateTime).ToString("s") & "Z"
                    Case Else
                        value = escapeVectorCharacters(kvp.Value.ToString)
                End Select

                props.AppendFormat("{0};{1}W|{2};", field, typeCode, value)
            End If
        Next
        Return props.ToString.TrimEnd(";")
    End Function

The first function, documentDetailString (lines 96-98), will help generate the basic structure of the document parameter’s value. It uses the EncodeString function from my last post to escape both the file name and all the metadata information between the brackets. When we use this later in an RPCParameter object you’ll see that we disable additional encoding since RPC is really finicky about this stuff.

The metadata information for a file is generated using the propertiesToString function (lines 100-124) and expects your metadata to be in a dictionary object where the internal column name is the key (string) and the value is the value (object). We loop through each property and build a strange looking string that indicates which column we are setting, the type of the value (and what action we want performed), and the value itself.

Generally, every property key needs to be set to the internal name of the column (not the display name). However, the Title column is a special case. When you specify Title it actually needs to be vti_title. This is taken care of in lines 105-106.

The meta_info string for each property has two parts separated by semicolons. The first is the internal name of the column, the second is information about the value. This second part also has two parts separated by a pipe. The first part will be two characters. The first character indicates the type of the value (S for everything but Boolean values where you will use B). The second character will always be W (write) and specifies the action to take.

We take care of this with a simple case statement that checks the type of the value (line 110). When it’s a Boolean, we use a B for the type character and set the value to the string true or false (lines 111-113). When it’s a DateTime, we still use S for the type character but we format the value into the standard Sortable format and slap a Z on the end (lines 114-115). For everything else, we specify S for type and use our escapeVectorCharacters method to escape it properly (lines 116-117).

Once we’ve looped through all the properties, we remove the final semicolon (line 123).

Unique File Names

Here’s a freebie function should you need it:

    Public Function UniqueFileName(originalFileName As String) As String
        Return "C" & DateTime.Now.ToString("yyMMddHHmmssfffffff") & "K" & Path.GetExtension(originalFileName)
    End Function

The UniqueFileName function above is a quick and dirty way to ensure that you aren’t overwriting your documents when uploading them in bulk.

Uploading

    Public Function UploadToSharePoint(webURL As String, libraryName As String, FolderPath As String, FileName As String, fileBytes As Byte(), properties As Dictionary(Of String, Object), SPVersion As String, Optional creds As NetworkCredential = Nothing, Optional KeepCheckedOut As Boolean = False, Optional Comment As String = "") As String
        Dim result As String = String.Empty

        If Not (String.IsNullOrEmpty(webURL) OrElse String.IsNullOrEmpty(libraryName) OrElse String.IsNullOrEmpty(FileName)) Then

            If properties Is Nothing Then properties = New Dictionary(Of String, Object)
            If Not (properties.ContainsKey("Title") OrElse properties.ContainsKey("vti_title")) Then
                properties.Add("Title", Path.GetFileNameWithoutExtension(FileName))
            End If

            Dim parameters As New List(Of RPCParameter)
            parameters.Add(New RPCParameter("document", documentDetailString(libraryName & "/" & FolderPath & "/" & FileName, properties), False, False))
            parameters.Add(New RPCParameter("put_option", "overwrite,createdir,migrationsemantics", False, False)) 'Overwrites files (otherwise use edit),creates the directory as needed, preserves creation/modification information
            parameters.Add(New RPCParameter("comment", Comment))
            parameters.Add(New RPCParameter("keep_checked_out", IIf(KeepCheckedOut, "true", "false")))

            Dim data As New List(Of Byte)
            'put document method: http://msdn.microsoft.com/en-us/library/ms479623(v=office.14).aspx
            data.AddRange(CommandBytes("put document", SPVersion, parameters))
            data.AddRange(Encoding.UTF8.GetBytes(vbLf))
            data.AddRange(fileBytes)

            result = ExecuteRPC(webURL, data.ToArray, creds)

        End If

        Return result
    End Function

End Module

The UploadToSharePoint function takes a web URL (this does not have to be the root site in a site collection), the name of the library to upload into, the folderpath (only the immediate directory will be created if needed, if you need to create a full path of directories or ensure they are there, use the CreateFolder function demonstrated in the previous post), the filename (great time to use that UniqueFileName function!), the filebytes, a property dictionary (string, object), the SharePoint version, and some optional parameters (credentials, keepcheckedout, version comments).

If the property dictionary doesn’t contain a Title property, we automatically add one using the filename without the extension (lines 136-138). Now it’s time to create the method parameters.

The first parameter for the put document method is the document parameter (line 141) which we create using the documentDetailString function. Notice that we don’t just specify the filename, but rather the exact path (library + folderpath + filename). We also disable string encoding in the RPCParameter object since this parameter requires very specific encoding that is handled in our helper function.

The second parameter, put_option, is where we specify some combination of the following three strings separated by commas:

  • overwrite: overwrites existing files with the same filename
  • createdir: creates the parent directory (does not create a full path)
  • migrationsemantics: preserves the author, editor and creation information (requires administrative permissions or it is ignored)

For our purposes we are specifying all three (line 142).

The third parameter, comment, is a comment to include for the given version of the file (line 143).

The final parameter, keep_checked_out, takes a string of “true” or “false” (line 144). When true, the document is checked in then checked right back out. When false, the document is just checked in.

To upload the document we must specify all of the method parameters first. We generate the appropriate bytes using our CommandBytes function (line 148). We then have to add the actual file bytes (line 150) but these need to be separated from the command bytes with a line feed (line 149).

 

That’s it! Now you can upload documents while setting the metadata all in a single call!



Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images