Checkout and Open PDF files from SharePoint Document Libraries
We have a customer that makes extensive use of Adobe Acrobat's integration with SharePoint, which allows for the checkout and editing of PDF files directly from Document Libraries. Recently, after applying a Cumulative Update to the SharePoint platform we lost this ability - files would open either in the browser, or directly in Acrobat but without prompting to 'Open' or 'Checkout and Open' as expected. As a quick aside, Adobe Reader also allows you to comment in PDF files, and this same 'Checkout and Open' integration functionality makes it possible to modify the PDF file in a Document Library.
For reference, here is what Adobe Reader looks like when things are working correctly:
Configuring SharePoint to support 'Check Out & Open' of PDF files
In order for this to work this manner, you need to configure the 'pdf' entry in the DOCICON.XML file as follows:
<Mapping Key="pdf" Value="icpdf.png" EditText="Adobe Acrobat" OpenControl="AdobeAcrobat.OpenDocuments" OpenApp="AcroRd32"/>
Then reboot the SharePoint server.
Once that's done, disable the 'Adobe PDF Reader' add-on in Internet Explorer. Otherwise, the PDFs will open in-browser without prompting. This is what the 'Manage Add-ons' should look like for Acrobat Reader:
Making it work
Despite having configured the server and client side appropriately, we were not seeing the 'Checkout and Open' prompt for PDF files. We opened a support case with Microsoft, and went through the usual troubleshooting steps (Have you configured the DOCICON.XML and set the ? Is the document library set to open files in the client application or the browser? Rebooted the server?) Making no progress with the first tier of support the case was escalated which resulted in a work-around that originated in an Adobe Community forum thread (https://forums.adobe.com/thread/1379554). The support engineer actually pointed me to the forum post which I thought was pretty humorous.
The work-around consists of two steps: first, place the PDFFIX.js file in the "C:Program FilesCommon Filesmicrosoft sharedWeb Server Extensions15TEMPLATELAYOUTS" directory on the SharePoint server; then, update the 'LinkFileName' column in the RootWeb of each affected site collection.
PDFFIX.js
Here's the PDFFIX.js which has been updated to support both HTTP and HTTPS sites:
(function () { if (typeof SPClientTemplates === 'undefined') return; var PdfCtx = {}; PdfCtx.Templates = {}; PdfCtx.Templates.Fields = { 'LinkFilename': { 'View': PdfClientLinkFilenameNoMenu } }; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(PdfCtx); })(); function GetExtension(szHref) { var sz = new String(szHref); var re = /^.*.([^.]*)$/; return (sz.replace(re, "$1")).toLowerCase(); } var stsOpen = null; function IsPdfClientInstalled() { if (stsOpen == null) { if (Boolean(window.ActiveXObject)) { try { stsOpen = new ActiveXObject("PdfFile.OpenDocuments"); } catch (e) { stsOpen = null; } } } return (stsOpen != null); } function OpenPdfInClient(pdfFileUrl) { var fRet = true; try { fRet = typeof stsOpen.ViewDocument2 != "undefined" && stsOpen.ViewDocument2(window, pdfFileUrl, ''); } catch (e) { fRet = false; }; if (event != null) { event.cancelBubble = true; event.returnValue = false; } return fRet; } function PdfNewGif(listItem, listSchema, ret) { if (listItem["Created_x0020_Date.ifnew"] == "1") { var spCommonSrc = GetThemedImageUrl("spcommon.png"); ret.push("<span class="ms-newdocument-iconouter"><img class="ms-newdocument-icon" src=""); ret.push(spCommonSrc); ret.push("" alt=""); ret.push(Strings.STS.L_SPClientNew); ret.push("" title=""); ret.push(Strings.STS.L_SPClientNew); ret.push("" /></span>"); } } function PdfClientLinkFilenameNoMenu(param1, param2, listItem, listSchema) { var ret = []; var fileUrl = listItem.FileRef; if (fileUrl != null && typeof fileUrl != 'undefined' && TrimSpaces(fileUrl) != "") { if (listItem.FSObjType == '1') { if (listSchema.IsDocLib == '1') { RenderDocFolderLink(ret, listItem.FileLeafRef, listItem, listSchema); } else { RenderListFolderLink(ret, listItem.FileLeafRef, listItem, listSchema); } } else { ret.push("<a class='ms-listlink' href=""); ret.push(listItem.FileRef); ret.push("" onmousedown="return VerifyHref(this,event,'"); ret.push(listSchema.DefaultItemOpen); ret.push("','"); ret.push(listItem["HTML_x0020_File_x0020_Type.File_x0020_Type.mapcon"]); ret.push("','"); ret.push(listItem["serverurl.progid"]); ret.push("')" onclick=""); var appInstalled = IsPdfClientInstalled(); var szExt = GetExtension(listItem.FileRef); if (appInstalled && szExt == 'pdf' && browseris.ie) { ret.push("return OpenPdfInClient('"); ret.push(window.location.protocol + "//"); ret.push(window.location.hostname); ret.push(listItem.FileRef); } else { ret.push("return DispEx(this,event,'TRUE','FALSE','"); ret.push(listItem["File_x0020_Type.url"]); ret.push("','"); ret.push(listItem["File_x0020_Type.progid"]); ret.push("','"); ret.push(listSchema.DefaultItemOpen); ret.push("','"); ret.push(listItem["HTML_x0020_File_x0020_Type.File_x0020_Type.mapcon"]); ret.push("','"); ret.push(listItem["HTML_x0020_File_x0020_Type"]); ret.push("','"); ret.push(listItem["serverurl.progid"]); ret.push("','"); ret.push(Boolean(listItem["CheckoutUser"]) ? listItem["CheckoutUser"][0].id : ''); ret.push("','"); ret.push(listSchema.Userid); ret.push("','"); ret.push(listSchema.ForceCheckout); ret.push("','"); ret.push(listItem.IsCheckedoutToLocal); ret.push("','"); ret.push(listItem.PermMask); } ret.push("')">"); var fileRef = listItem["FileLeafRef"]; if (fileRef != null) { var index = fileRef.lastIndexOf('.'); fileRef = index >= 0 ? fileRef.substring(0, index) : fileRef; } ret.push(fileRef); ret.push("</a>"); PdfNewGif(listItem, listSchema, ret); } } else { ret.push("<nobr>"); ret.push(listItem["FileLeafRef"]); ret.push("</nobr>"); } return ret.join(''); }
Update LinkFileName
To set the LinkFilename we've scheduled the following PowerShell script to run periodically so that any newly-created site collections are updated automatically:
<# This script will loop through all sites in a web application and set the LinkFileName to use a custom JavaScript file that fixes opening of PDFs #> #Add SharePoint PowerShell SnapIn if not already added if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) { Add-PSSnapin "Microsoft.SharePoint.PowerShell" } $targetWebAppURL = "https://TARGETWEBAPPURL" # comma separated list of URLs to ignore $ExclusionURLs = "" # Go Through Every Site and enable the target feature Get-SPWebApplication $targetWebAppURL | Get-SPSite -Limit ALL | ForEach-Object { # Check for Exclusion if(!($ExclusionURLs -contains $_.URL)) { $web = $_.RootWeb $field = $web.Fields.GetFieldByInternalName("LinkFilename") if($field.JSLink -eq "/_layouts/15/PDFFIX.js") { # JSLink already set... } else { Write-Output $_.URL Write-Output "Setting JSLink..." $field.JSLink = "/_layouts/15/PDFFIX.js" $field.Update($true) } } }
As evidenced in the forums discussing the issue it was obvious that many others were also experiencing the same behaviour, but it wasn't completely consistent - for some it 'just worked'. This got me thinking that the issue only presented itself with particular patch levels, which was certainly our experience. Initially the customer was running the June 2013 Cumulative Update in which the 'Checkout and Open' worked out-of-the-box; it was only after patching to April 2014 CU that we lost the functionality. So far, I've been able to test the funcionality on the following patch levels and have found only a few where it works out-of-the-box.
Working:
- RTM
- June 2013 CU
Requires work-around (PDFFIX.js):
- March 2013 PU
- Service Pack 1 (SP1)
- April 2014 CU
- July 2014 CU
- September 2014 CU
- November 2014 CU
- December 2014 CU
Now, in wrapping up the case with Microsoft Support, the engineer let me know that this issue has been logged as a bug and is before the Product Management group; however as expected, there was no way to know if or when this would be fixed. I'm hoping that it does get fixed soon (and for good!) but this is where we as the SharePoint community and customers need to make our voices heard. If you've configured this functionality on a patch level that I've not listed, would you mind dropping me a note in the comments and I'll update the list so that we've a comprehensive list? This will provide yet another data point when considering which patch level to take your SharePoint farm to.
It’s Time To Transform
Let us show you how much easier your work life can be with Bonzai Intranet on your team.