When you open a file from Sharepoint, it will receive a short term lock that will prevent others to change some properties on the file.
This protection can be useful, but also very annoying, for example when the file is not closed properly, then the lock could stay « forever ».
There are many posts on the web about it.
I found one that has been super useful: https://pholpar.wordpress.com/2014/04/07/how-to-use-javascript-to-delete-short-term-locks-from-documents-opened-from-sharepoint/
The author explains very well the different steps what I’m trying to summarize:
- Send a request to
_vti_bin/_vti_aut/author.dll
with special headers/body - Auth.dll will provide the
lockid
- Send a request to
_vti_bin/cellstorage.svc/CellStorageService
with special headers/body, included thelockid
- The file is unlocked
The code to send to CellStorageService, and provided by the author, didn’t work for me. I’ve had to use Fiddler and open the document into Office on my computer to see the kind of requests send by it to unlock a document. Based on it, I’ve re-built the code and you can find my solution below.
Tested on Sharepoint 2013 On-Promise only. I don’t know if this solution works for Sharepoint Online or other version.
Also note that I use $SP().ajax()
from SharepointPlus, but it’s equivalent to the $.ajax
from jQuery.
// full path to the document var docUrl = "https://website.com/website/Doc_Library/Test.docx"; // start by querying author.dll to find the lockid and the user who locked it $SP().ajax({ url: 'https://website.com/website/_vti_bin/_vti_aut/author.dll', headers:{ "Content-Type": "application/x-www-form-urlencoded", "MIME-Version": "1.0", "Accept": "auth/sicily", "X-Vermeer-Content-Type": "application/x-www-form-urlencoded" }, body: 'method=getDocsMetaInfo%3a14%2e0%2e0%2e6009&url%5flist=%5b' + encodeURIComponent(docUrl) + '%5d&listHiddenDocs=false&listLinkInfo=false', }).then(function(source) { // go thru the source page returned to find the lockid and current user var nextLine = false; var ret = { "lockid":"", "user":"", when:"" }; source.split("\n").forEach(function(line) { if (line.indexOf("vti_sourcecontrollockid") !== -1) nextLine="lockid"; // vti_sourcecontrollockid -> the lockid to use later else if (line.indexOf("vti_sourcecontrolcheckedoutby") !== -1) nextLine="user"; // vti_sourcecontrolcheckedoutby -> username of the user who locked it else if (line.indexOf("vti_sourcecontrollockexpires") !== -1) nextLine="when"; // vti_sourcecontrollockexpires -> when the server is supposed to unlock it else if (nextLine !== false) { ret[nextLine] = line.slice(7).replace(/([0-9]|[1-9][0-9]|[[01][0-9][0-9]|2[0-4][0-9]|25[0-5]);/g, function (str, match) { return String.fromCharCode(match); }); nextLine = false; } }); if (!ret.lockid) { alert("Not Locked") } else { // compose a request based on what Microsoft Office sends to the Sharepoint server // found using Fiddler var releaseLockReq = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><RequestVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/><RequestCollection CorrelationId="{96A244BD-D13B-4696-9355-231FB673BC4F}" xmlns="http://schemas.microsoft.com/sharepoint/soap/"><Request Url="'+docUrl+'" UseResourceID="true" UserAgent="{1984108C-4B93-4EEB-B320-919432D6E593}" UserAgentClient="msword" UserAgentPlatform="win" Build="16.0.8201.2102" MetaData="1031" RequestToken="1"><SubRequest Type="ExclusiveLock" SubRequestToken="1"><SubRequestData ExclusiveLockRequestType="ReleaseLock" ExclusiveLockID="'+ret.lockid+'"/></SubRequest></Request></RequestCollection></s:Body></s:Envelope>'; // we send it to the webservice cellstorage.svc $SP().ajax({ url:'https://website.com/website/_vti_bin/cellstorage.svc/CellStorageService', body:releaseLockReq, headers:{ 'Content-Type':'text/xml; charset=UTF-8', 'SOAPAction': "http://schemas.microsoft.com/sharepoint/soap/ICellStorages/ExecuteCellStorageRequest" } }) .then(function(res) { if (res.indexOf('ErrorCode="Success"') !== -1) alert("Success") // the file has been unlocked else alert("Failed") }) } })
I hope it will be useful to someone else!