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>