Wednesday, September 19, 2012

How to upload large files to SharePoint document library using RPC method from Silverlight application

Well this is very common scenario and we come accross during our development when we want to upload large files. If we try to use silverlight client object model it will not allow us to upload large files and result in error.
There are various options suggested by various bloggers and even on MSDN which tell us to increase message size. But to do that we require server access. What if we dont have server access and allowed to write code only on client side?
I was in simillar situation where I wanted to upload large file from my Silverlight application.
And finally I decided to go for RPC methods available for SharePoint.
 RPC is an interprocess communication technique that allows client and server software to communicate. For more details of RPC you can visit "Wikipedia" and "Technet" articles.
As we can use RPC calls to communicate with SharePoint from any platform it is very powerful way of communication.
Here I am posting code for uploading large file to SharePoint document library. Hope this will help to those who are searching for similar solution.

public void UploadFile(string CurrentWebUrl,string serviceName, string filePath, FileStream stream, string userDomainName)

{

newFileData =
null;

newFileData = new byte[stream.Length];

stream.Read(newFileData, 0, Convert.ToInt32(stream.Length));
 string requestUrl = CurrentWebUrl + "/_vti_bin/_vti_aut/author.dll";

string method = GetEncodedString("put document:14.0.0.5123");

serviceName = GetEncodedString("/" + serviceName);
 string putOption = "overwrite";

string metaInfo = "[vti_modifiedby;SW|" + userDomainName + ";vti_author;SW|" + userDomainName + "]]";

string comments = GetEncodedString("File uploaded using RPC call");

string docDetails = string.Format("[document_name={0};meta_info={1}", filePath, metaInfo);

docDetails = GetEncodedString(docDetails);

rpcCallString =
"method={0}&service_name={1}&document={2}&put_option={3}&comment={4}&keep_checked_out=false\n";

rpcCallString = String.Format(rpcCallString, method, serviceName, docDetails, putOption, comments).Replace("_", "%5f");

 HttpWebRequest wReq = WebRequest.Create(requestUrl) as HttpWebRequest;

wReq.Method = "POST";

wReq.Headers["Content"] = "application/x-vermeer-urlencoded";

wReq.Headers["X-Vermeer-Content-Type"] = "application/x-vermeer-urlencoded";

wReq.BeginGetRequestStream(new AsyncCallback(gotRequestStream), wReq);

}



private void gotRequestStream(IAsyncResult asynchronousResult)

{HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;

Stream requestStream = webRequest.EndGetRequestStream(asynchronousResult);

List<byte> uploadData = new List<byte>();

uploadData.AddRange(Encoding.UTF8.GetBytes(rpcCallString));

uploadData.AddRange(newFileData);
 
byte[] fileData = uploadData.ToArray();

requestStream.Write(fileData, 0, fileData.Length);

requestStream.Close();

webRequest.BeginGetResponse(
new AsyncCallback(gotResponse), webRequest);

}

private void gotResponse(IAsyncResult asynchronousResult)

{HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;

HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);

Stream responseStream = webResponse.GetResponseStream();

StreamReader reader = new StreamReader(webResponse.GetResponseStream());
 
string responseString = string.Empty;

responseString = reader.ReadToEnd();byte[] fileBuffer = Encoding.UTF8.GetBytes(responseString);

responseStream.Close();

reader.Close();

webResponse.Close();
if (responseString.IndexOf("\n<p>message=successfully") < 0)

{throw new Exception(responseString);
}
}

Now let's have a look at the parameters used in this call.
Here we are using method "put document" and "14.0.0.5123" is server extension version.
Service name is server relative URL of your site.
In document parameter we are providing to fileds "document_name" and "meta_info". document name is nothing but the path at which we want to upload file including file name and meta info sets the metadata of the document to be uploaded. You can observe in code that I am setting two fields like "Modified By" and "Author" of the document. vti_modifiedby is column name and userDomainAlias is value to set. "SW" is field type. Syntax for various field types is different. This is very simple example of setting meta info. But I am not able to get any documentation which will give me idea about rest of the field types. I will post updates once I get details about other field types.
Next parameter is put_option where you can provide "overwrite" if you want to overwrite existing file with same name else you can provide "edit".
Next two parameters comment and keep_checked_out are very straight forward and do not require any explaination.
In case of RPC calls it is confusing how to pass parameters, mostly in case of file paths. So here is the example of how will you call this upload method.

UploadFile("http://myserver/sites/prasad/teamsite/", "sites/prasad/teamsite", "Shared Documents/document1.docx", stream, "myserver\\prasad.kulkarni");

I have used one utility method for encoding of string. Here it is for your reference.

public string GetEncodedString(string SourceString)
{if (!string.IsNullOrEmpty(SourceString))

{ return HttpUtility.UrlEncode(SourceString).Replace(".", "%2e").Replace("_", "%5f");
}else

{return SourceString;

}
}

If you have any doubts please post your comments. For more information of method used here see this MSDN page.

I hope you can upload files upto 2 GB which is default SharePoint limit.

Enjoy uploading large files....

2 comments:

  1. I used RPC for file download, but I keep getting Server unavailable 503, for large, any idea on how to get rid of this apart from retries!?

    ReplyDelete