In one of my previous post, https://realmpksharepoint.wordpress.com/2014/01/19/upload-a-file-to-sharepoint-using-client-object-model/ , I had shown how we can upload documents to SharePoint using CSOM. Though, the client object model was working perfectly for smaller documents, it started throwing time-out errors when I tried to upload a file of size around 40MB (previously, I was uploading documents < 2MB).
So to upload large documents I am going to use RPC. 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.
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:15.0.0.4420"); 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.UserAgent = "FrontPage"; wReq.UseDefaultCredentials = false; Uri targetSite = new Uri(this.ctx.Web.Url); //Get the credential for authentication SharePointOnlineCredentials spCredentials = (SharePointOnlineCredentials)this.ctx.Credentials; //Retrieve the authentication cookie with the help of credentials string authCookieValue = spCredentials.GetAuthenticationCookie(targetSite); wReq.CookieContainer = new CookieContainer(); wReq.CookieContainer.Add( new Cookie("FedAuth", authCookieValue.TrimStart("SPOIDCRL=".ToCharArray()), String.Empty, targetSite.Authority)); 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 message=successfully" ) < 0) { //Indicates that the SharePoint has returned an error message. The document might have got uploaded also so one should better check the message first. throw new Exception(responseString); } }
Now, let’s evaluate this.
- Here we are using the method, “put document” and, “15.0.0.4420” is server extension version.
- Service name is server relative URL of your site.
- In document parameter we are providing to fields “document_name” and “meta_info”. Document name is the path at which we want to upload the file including the file name and meta info sets the metadata of the document to be uploaded. MetaInfo is a system site-column where SharePoint stores custom values related to that particular ListItem.
- 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.
- For authentication, we’re using the CookieContainer of HTTPWebRequest.
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/teamsite/", "sites/teamsite", "Shared Documents/document1.docx", fileStream, "Piyush Singh");
One utility method has been used here for encoding of string. Here it is for the reference.
public string GetEncodedString(string sourceString) { if (!String.IsNullOrEmpty(sourceString)) { return HttpUtility.UrlEncode(sourceString).Replace(".", "%2e").Replace("_", "%5f"); } else { return sourceString; } }
You can get more info about put document here, http://msdn.microsoft.com/en-us/library/ms479623.aspx.
It has been said that in this way we can upload document up to 2GB to the site. Well, I have tested it for the documents of size little over 100MB and it’s working fine.
Also, you can visit the following post to upload files up to 10GB to SharePoint Online,
https://realmpksharepoint.wordpress.com/2016/07/22/upload-large-files-to-sharepoint-online/.
Keep up the great work guyz.
LikeLike
Could you please share this code in Jquery using SP.JS?
LikeLike