4

I've created a VF page that allows users to select a list of custom objects related to a particular case, update some field information and attach pictures to any of these related objects. When done, the user clicks on an email that generates an email based on a VF Email template. This part works great.

Instead of sending multiple image attachments on this email, I created a VF page that displays all of these images, and was attempting to generate it as a PDF attachment to attach to the case.

When I load the VF page (which has renderAS="PDF"), it looks great and works as expected.

When I call it from my custom controller using the getContent() method, it is sending a file that I am unable to open using Adobe. When I try I receive the error "insufficient data for an image", and even the text on the page does not render (though, oddly, the table is visible).

I have no clue how to attempt and troubleshoot it, so I will appreciate any help!

Here is my controller extension part which calls my page:

Messaging.EmailFileAttachment myAttach = new Messaging.EmailFileAttachment();
myAttach.setFilename(This.Cas.CaseNumber+'_Related_Pictures.pdf');
myAttach.setContentType('application/pdf');
PageReference myPdf = Page.IDS_Quote_Pictures_PDF;
mypdf.setRedirect(true);
myPDF.getParameters().put('ID' , this.Cas.ID);
blob b = myPdf.getContentAsPdf();
myAttach.setbody(b);
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setWhatID(Cas.ID);
email.setTargetObjectId(toContacts[0].theContact.id);
EmailTemplate templateId = [Select id from EmailTemplate where name = 'IDS RMA Quote Email'];
email.setTemplateID(templateId.Id);
email.setSaveAsActivity(true);
email.setToAddresses(toAddresses);
email.setCCAddresses(ccAddresses);
email.setOrgWideEmailAddressId([SELECT id, displayName FROM OrgWideEmailAddress WHERE DisplayName = 'I.D. Systems RMA Department'].id);
if (myAttach != NULL) {
    email.setFileAttachments(new Messaging.EmailFileAttachment[] {myAttach});
        }

And here is the custom controller that the actual PDF VF page calls:

public class IDS_RMA_Quote_Pictures_Getter{

// Wrapper class to wrap an attachment with a selection and some related details in text
public class attachFile {
    public Attachment theFile {get;set;}
    public String belongsTo {get;set;}

    public attachFile(Attachment theFile) {
        this.theFile = theFile;
    }
}

public final Case cas;
//private final ID cas;
private List<attachFile> readyAttachments;

public IDS_RMA_Quote_Pictures_Getter(){
    //this.cas = (case)stdController.getRecord();        
    Cas = [Select ID, Subject, CaseNumber, Type_of_RMA__c, Date_RMA_Received__c FROM Case WHERE ID =: ApexPages.CurrentPage().getParameters().get('id')];
}

public Case getCas() {
    return cas;   
}


public List<attachFile> getReadyAttachments() {
    System.debug('Starting Getter');
    List<device__C> deviceList = new List<Device__c>();
    deviceList = [SELECT Name,
                  Part_Number__R.Name,
                  Part_Number__R.Description__c,
                  Problem__c,
                  Visual_Inspection_Notes__c,
                  Quoted_Price__c,
                  Quote_Status__c,
                  Customer_Damage__c,
                  In_Warranty__c
                  FROM Device__c 
                  where Quote_Status__c =: 'Quoting' 
                  AND Case__c =: Cas.ID]; 
    System.debug('Devices: '+deviceList);

    List<ID> allDeviceIDs = new List<ID>();
    For (device__c d : deviceList) {
        allDeviceIDs.add(d.ID);   
    }
    System.Debug('Device IDs: '+allDeviceIDs);

    List<Attachment> allAttachments = new List<Attachment>();
    allAttachments = [SELECT ID, Name, ParentID, body, ContentType 
                      FROM Attachment 
                      WHERE name != : 'Device_QR_Code.png'
                      AND ContentType LIKE 'image/%'
                      AND (ParentID IN : allDeviceIDs
                             OR ParentID = : cas.ID)
                     Order by ID desc];
    System.debug('Selected # of Attachments: '+allAttachments.size());

    List<attachFile> readyAttachments = new List<attachFile>();
    integer counter = 1;

    for (attachment att : allAttachments) {
        attachFile AF = new attachFile(att);
        if (att.ParentID == cas.ID) {
            af.belongsTo = 'Attached to case';
            System.Debug('Device being added to list: '+af);
        } else {
            for (device__c dvc : deviceList) {
                if (att.ParentID == dvc.ID){
                    af.belongsTo = 'For Part Number ' +dvc.part_number__r.name+' Serial Number: '+dvc.Name;                    
                }
            }   
        }
        readyAttachments.add(af);
        System.Debug('Device being added to list: '+af);
    }
    System.Debug('Added file to readyAttachments');
    System.debug('Ready Attachments: '+readyAttachments.size());

    return readyAttachments;
}

}

and lastly, here is the PDF VF page:

<apex:page title="Quote for Repair" showHeader="false" controller="IDS_RMA_Quote_Pictures_Getter">
<apex:stylesheet value="{!URLFOR($Resource.RepairPDF, 'RFStyle.css')}"/>
<Apex:form >
    <apex:pageBlock >
    <apex:pageMessages />
        <table width = "100%" align="center">
            <tr width = "100%">
                <td width = "50%" align="left">
                    <apex:image value="{!URLFOR($Resource.RepairPDF, 'logo.jpg')}"/>
                </td>
            </tr>
            <tr>
                <td height="20px">
                    <!-- Spacing between logo and table-->
                </td>
            </tr>
            <!--<apex:outputText value="Dear Customer"/>-->
            <table width="100%" Class="grid">
                <tr>                        
                    <td width="50%" colspan="2" align = "center">
                        <apex:outputText styleClass="headertext" value="Pictures related to RMA #{!cas.CaseNumber}"/>
                    </td>
                </tr>
                <tr>
                    <td width="50%" align = "left" >
                        <apex:outputText value="RMA Type : "/>
                        <apex:outputText value="{!cas.Type_of_RMA__c}"/>
                    </td>
                    <td align = "left">
                        <apex:outputText value="Date RMA Received: "/>  
                        <apex:outputText value="{!cas.Date_RMA_Received__c}"/>
                    </td>
                </tr>
            </table>
            <!--Here starts the Device List-->
            <apex:variable value="{!1}" var="pgCount"/> 
            <apex:pageBlockSection title="Attached Images" columns="1">
                <apex:repeat value="{!readyAttachments}" var="ra">
                    <div style="{!if(pgCount = 1, 'page-break-after:auto;', 'page-break-after:always;')}">
                        <apex:outputText value="{!ra.belongsTo}" />
                        <apex:image url="/servlet/servlet.FileDownload?file={!ra.theFile.ID}"/>
                        <apex:variable var="pgCount" value="{!pgCount+ 1}"/>
                    </div>
                </apex:repeat>
            </apex:pageBlockSection>
        </table>            
    </apex:pageBlock>            
</Apex:form>

  • I'd start by saving the PDF that the VF page creates with renderAS="PDF" and comparing the file size with the one attached to the email. They should be exactly the same size. If not, then the one that doesn't open from the email has been corrupted at some point. – Daniel Ballinger Oct 24 '13 at 0:13
  • I do something similar. As also suggested by Daniel. I set the page with renderAs="PDF" and in the controller extension part which calls the page I use getContent() instead of getContentasPDF() – Marcel Meijer Oct 24 '13 at 6:59
  • Thanks guys, but I've learned that even the one generated by the VF page is viewable through the browser, but I am still unable to open it using Acrobat Standard 9.5... – Ohadios Oct 25 '13 at 12:20
4

I strongly suspect the line below in your visualforce code and it's closing tag are at the root of your problem:

<apex:pageBlockSection title="Attached Images" columns="1">

</apex:pageBlockSection>

If you look at Best Practices for Rendering PDFs you'll see that <apex:pageBlock> is listed under "Components That Are Unsafe to Use in a PDF".

I recommend you redesign your page to use other HTML (another table perhaps) instead of the <apex page block> and see if that doesn't solve your problem.

1

Well, in my case, it turns out that the image I had referenced from the Static Resource was the culprit for this issue. Even though the file is a valid JPG, and is visible on some other VF pages I created, it was not printing on the PDF (which caused me to not think of it). When I removed this image, the file size dropped dramatically, and I can now open the file in Adobe reader without a problem.

Thank you for the recommendation.

  • You should mark this as the accepted answer to your question since it was what ultimately solved your problem. Thanks for letting us know. I just saw this today when someone upvoted my answer. – crmprogdev Sep 22 '14 at 14:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.