function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Afzaal HassanAfzaal Hassan 

link address not correct, pdf not opening and throwing error

I created a visualforce page that lists several information in a table format. One component is a pdf attachment. When I am clicking on this attachment, I am getting the following error message (when its redirecting to the url):

Unable to Access Page
The value of the "file" parameter contains a character that is not allowed or the value exceeds the maximum allowed length. Remove the character from the parameter value or reduce the value length and resubmit. If the error still persists, report it to our Customer Support team. Provide the URL of the page you were requesting as well as any other related information.

I clearly am not passing the right URL path but I am not sure what to do. Below is my visualforce code:
<apex:page standardController="Opportunity" extensions="LPP_PDKPrintingController" lightningStylesheets="true">
    <apex:form >
     <apex:pageBlock title="Shipped" rendered="{!pdkOption=='Shipped'}">
            <apex:actionFunction name="searchServer" action="{!runSearch}" rerender="shippedList">
                <apex:param name="accountName" value="" />
                <apex:param name="LID" value="" />
                <apex:param name="JobNo" value="" />
            </apex:actionFunction>
            <table cellpadding="5" cellspacing="5">
            <tr>
                <td style="font-weight:bold;">Account Name<br/>
                    <input style="width:250px" type="text" id="accountName" onkeyup="if(this.value==''){doSearch();}" onkeypress="if(pressedEnter(event)){doSearch();}"/><input type="button" onclick="doSearch();" value="Search"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                </td>
                <td style="font-weight:bold;">LID #<br/>
                    <input type="text" id="LID" onkeyup="if(this.value==''){doSearch();}" onkeypress="if(pressedEnter(event)){doSearch();}"/><input type="button" onclick="doSearch();" value="Search"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                </td>
                <td style="font-weight:bold;">Job #<br/>
                    <input type="text" id="JobNo" onkeyup="if(this.value==''){doSearch();}" onkeypress="if(pressedEnter(event)){doSearch();}"/><input type="button" onclick="doSearch();" value="Search"/>
                </td>
            </tr>
            </table>              
            <apex:outputPanel id="shippedList">
//THIS BELOW LINE IS THE KEY COMPONENT AS IT RELATES TO THE PDF
            <apex:pageBlockTable value="{!shippedItems}" var="s">
                <apex:column headerValue="PDF">
                    <apex:outputLink target="_blank" value="{!s.attach}"><apex:image rendered="{!IF(s.attach != null,true,false)}" url="{!$Resource.pdf}" width="25" height="25"/></apex:outputLink>
                </apex:column>
                <apex:column headerValue="Printed Date">
                    <apex:outputText value="{!s.printDate}"/>
                </apex:column>      
                    
            </apex:pageBlockTable>  
            </apex:outputPanel>
                               
        </apex:pageBlock> 
        </apex:outputPanel>
        
    </apex:form>
</apex:page>

The apex controller is below:
public class LPP_PDKPrintingController {
   
    Private ApexPages.StandardController standardController;
    Public List<Opportunity> printList {get;set;}
    Public List<Opportunity> suppliesList {get;set;}    
    Public List<shippedItem> shippedItems {get;set;}    
    Public Integer numToPrint {get;set;}
    Public Integer numSupplies {get;set;}    
    Public Integer numShipped {get;set;}
    Public String pdkOption {get;set;}
    Public Date dateCompare = system.today()+21;
    Public Date dateCompare2 = system.today()+49;    
    Public Date dateHistory = system.today()-90;
    Public Integer batchSize {get;set;}
    Public Boolean rushOnly {get;set;}
    
    
    public LPP_PDKPrintingController (ApexPages.StandardController controller){
        //Default batch size
        batchSize = 200;
        //List of PDKs to be shipped                      
        printList = new List<Opportunity>();
        printList = [SELECT Id, Name, Account.Name, Account.LID__c, Job__c, WPA__c, CloseDate, Start_Date__c, StageName, Confirmation_Kit_Ship_Status__c
                   FROM Opportunity WHERE (Confirmation_Kit_Ship_Status__c = '' or Confirmation_Kit_Ship_Status__c = 'Not Shipped' or Confirmation_Kit_Ship_Status__c = 'Reship') and
                   (Account.LID__c != null and Authorizer__c != null) and 
                   ((Year__c = '2017' and (Season__c = 'Summer' or Season__c = 'Fall')) or (Year_Value__c > 2017 and Season__c != null)) and
                   (stagename='Closed Won' or stagename='Confirmed' or stagename='Scheduled') and ((start_date__c >=TODAY and start_date__c <= :dateCompare) 
                   or (X3_Week_Prior_Call_Complete__c = true and start_date__c <= :dateCompare2))
                   order by Start_Date__c LIMIT 1000];       
        numToPrint = printList.size();  
        
        //List of Additional Supplies to be shipped        
        suppliesList = new List<Opportunity>();
        suppliesList = [SELECT Id, Name, Account.Name, Account.LID__c, Job__c, WPA__c, CloseDate, Start_Date__c, StageName,
                   Request_Additional_Supplies_Details__c
                   FROM Opportunity WHERE (Request_Additional_Supplies_Details__c != null) and (Account.LID__c != null and Authorizer__c != null)
                   and ((Year__c = '2017' and (Season__c = 'Summer' or Season__c = 'Fall')) or (Year_Value__c > 2017 and Season__c != null))
                   and (stagename='Closed Won' or stagename='Confirmed' or stagename='Scheduled') LIMIT 1000];
        numSupplies = suppliesList.size();          
        
        //List of PDKs that have been shipped
        List<Opportunity> printedList = new List<Opportunity>();
        Map<Id, Opportunity> printedMap = new Map<Id, Opportunity>([SELECT Id, Name, Account.Name, Account.LID__c, Job__c, WPA__c, CloseDate, Start_Date__c, StageName, PDK_Printed__c
                   FROM Opportunity WHERE (Confirmation_Kit_Ship_Status__c = 'Shipped' and PDK_Printed__c != null)
                   and (Account.LID__c != null and Authorizer__c != null) and (stagename='Closed Won' or stagename='Confirmed' or stagename='Scheduled') and start_date__c >=:dateHistory order by PDK_Printed__c Desc LIMIT 1000]);
        
        List<ContentDocumentLink> contentList = new List<ContentDocumentLink>();
        contentList = createContentDocumentLinkList(printedMap);  
        shippedItems = createShippedList(contentList, printedMap);    

        numShipped = shippedItems.size();
    }       
    
    // runs the search with parameters passed via Javascript
    public PageReference runSearch() {
        String accountName = Apexpages.currentPage().getParameters().get('accountName');
        String LID = Apexpages.currentPage().getParameters().get('LID');
        String JobNo = Apexpages.currentPage().getParameters().get('JobNo');
        String query = 'SELECT Id, Name, Account.Name, Account.LID__c, Job__c, WPA__c, CloseDate, Start_Date__c, StageName, PDK_Printed__c ';
        query += 'FROM Opportunity WHERE (Confirmation_Kit_Ship_Status__c = \'Shipped\' and PDK_Printed__c != null) ';            
        query += 'and (Account.LID__c != null and Authorizer__c != null) and (stagename=\'Closed Won\' or stagename=\'Confirmed\' or stagename=\'Scheduled\') and start_date__c >=:dateHistory ';
        query += 'and LID__c LIKE \'%'+ String.escapeSingleQuotes(LID)+'%\'';
        query += 'and Account.Name LIKE \'%'+ String.escapeSingleQuotes(accountName)+'%\'';        
        query += 'and WPA__c LIKE \'%'+ String.escapeSingleQuotes(JobNo)+'%\'';
        List<Opportunity> printedList = new List<Opportunity>();
        printedList = Database.query(query);       
        Map<Id, Opportunity> printedMap = new Map<Id, Opportunity>(printedList);        
        
        List<ContentDocumentLink> contentList = new List<ContentDocumentLink>();        
        contentList = createContentDocumentLinkList(printedMap);  
        shippedItems = createShippedList(contentList, printedMap);     
        numShipped = shippedItems.size();
        return null;

    }
    
                
 
    
    
    public class shippedItem {
        Public String attach {get;set;}
        Public String printDate {get;set;}
        Public String oppName {get;set;}
        Public String accName {get;set;}
        Public String lid {get;set;}
        Public String job {get;set;}
        Public String start {get;set;}
        Public String stage {get;set;}
    }
    Public List<shippedItem> createShippedList(List<ContentDocumentLink> fileList, Map<Id, Opportunity> oppMap)
    {
        Opportunity o = new Opportunity();
        List<shippedItem> shipList = new List<shippedItem>();
        for (ContentDocumentLink cdl : fileList) {

            o = oppMap.get(cdl.LinkedEntityId);
            system.debug(cdl.LinkedEntityId);
            if (o != null) {
                shippedItem s = new shippedItem();
                system.debug(cdl.ContentDocument.Id);
                s.attach = '/servlet/servlet.FileDownload?file='+cdl.ContentDocumentId;
 
                system.debug(s.attach);
                s.printDate = cdl.ContentDocument.CreatedDate.format();
                s.oppName = o.Name;
                s.accName = o.Account.Name;
                s.lid = o.Account.LID__c;
                s.job = o.WPA__c;
                if (o.Start_Date__c != null) {
                    s.start = o.Start_Date__c.format();
                }
                s.stage = o.StageName;
                shipList.add(s);                      
            }
        }      
        return shipList;        
    }
 
    public List<ContentDocumentLink> createContentDocumentLinkList(Map<Id, Opportunity> printedMap)
    {
        List<ContentDocumentLink> contentReturnList = new List<ContentDocumentLink>();
        Set<Id> printedMapIds = printedMap.keySet();
        contentReturnList = [SELECT ContentDocument.Id, ContentDocument.CreatedDate, ContentDocument.Title, LinkedEntityId from ContentDocumentLink where ContentDocument.Title LIKE 'SFP%' and LinkedEntityId IN :printedMapIds order by ContentDocument.CreatedDate Desc LIMIT 1000];        
        return contentReturnList;
    }
    /*
    * createContentVersion method
    * Created by: Brock Irvine
    * params: PDKBatchPrintObject, pdfPageBlob
    * return: contentReturnList
    */    
    public ContentVersion createContentVersion (LPP_PDKBatchPrint__c PDKBatchPrintObject, Blob pdfPageBlob)
    {
        ContentVersion cv = new ContentVersion();
        cv.VersionData = pdfPageBlob;
        cv.Title = string.valueOf(System.Today()).left(10) + 'BatchPDK.pdf';
        cv.ContentLocation = 'S';
        cv.PathOnClient = string.valueOf(System.Today()).left(10) + 'BatchPDK.pdf';   
        cv.FirstPublishLocationId = PDKBatchPrintObject.Id;             
        insert cv;     
        return cv;
    }
}

I have system debug outputs in there and I am getting the followng values for the system.debug:
USER_DEBUG [145]|DEBUG|0061C00000aYYoaQAG //this is the entityid
18:27:06:642 USER_DEBUG [148]|DEBUG|06923000000GPobAAG //thats the contentdocument.id
USER_DEBUG [151]|DEBUG|/servlet/servlet.FileDownload?file=06923000000GPobAAG //so this is what the url would be

I checked the static respurces and out this id and i see a record which has all the details written and a pdf attachment.

Can someone please let me know what is wrong? Do I have the right id but the wrong path written? Should the path be a different format. Because when I am pasting that exact link in my browser, I also get an error.
Thank you