1

Here is my attachment loop to convert into Salesforce Files. The document as Files is created along with the title and content type however it has no content or sometimes '1' or 'MQ==' which is not expected. Any help would be appreciated.


    public static void afterInsert(List<Attachment> attachinserted){
        
        Set<ID> agreementset = New Set<ID>();
        List<ID> attachedIDs = New List<ID>();
        for(Attachment attach : attachinserted){
            if(attach.ParentId.getSobjectType() == Apttus__APTS_Agreement__c.SobjectType){
               agreementset.add(attach.ParentId);
               attachedIDS.add(attach.Id);
            }
        }
        //Holds agreements with new Attachments      
        List<Apttus__APTS_Agreement__c> agreementAUS = [Select Id FROM Apttus__APTS_Agreement__c 
                                                        WHERE CNG_AUS_RecordType__c = TRUE AND ID IN:agreementset];
        
        //Holds attachments from correct Recordtypes
        List<Attachment> attachtoupdate = [SELECT Id, ParentId, Name, IsPrivate, Body, OwnerId, CreatedById, CreatedDate,ContentType, Description FROM Attachment 
                                                        WHERE ParentId IN:agreementAUS AND ID IN:attachedIDs];  
                
//Conversion of Attachments into ContentVersions                
          
//map Attachment Id with ContentVersion record
                Map<Id,ContentVersion> attachmentCVs = new Map<Id,ContentVersion>();
                List<Attachment> attdelete = new List<Attachment>();
//Map —> Attachment – Attachment Parent Id 
                Map<Id,Id> attachmentParentIds = new Map<Id,Id>();
                List<ContentVersion> contentversionupdate=new List<ContentVersion>();
//Generating file version using content version object
        //Set<Id> contentDocumentIdSet = new Set<Id>(); 
        if(!attachtoupdate.isEmpty()){
                for(Attachment att : attachtoupdate) {
                     ContentVersion cv = new ContentVersion();
                     cv.ContentLocation = 'S';
                     cv.PathOnClient ='/'+att.Name +'.doc';
                     cv.Origin = 'H';
                     cv.OwnerId = att.OwnerId;
                     cv.Title = att.Name;
                     cv.VersionData = att.body;
                    // cv.VersionData = Blob.valueOf(EncodingUtil.base64Encode(att.body));
                    
                    /* String fileContent = att.body!=Null ? 
                         string.valueOf(att.Body).replaceAll('<','&lt;')
                                                 .replaceAll('>','&gt;')
                                                 .replaceAll('&','&amp;')
                                                 .replaceAll('"','&quot;')
                                                 .replaceAll('[','&#39;')
                                                 .replaceAll('\'', '&#39;'):'.';*/                       
                    cv.FirstPublishLocationId = att.ParentId;                   
                    attachmentCVs.put(att.Id,cv);
                    attachmentParentIds.put(att.Id,att.ParentId);
                    attdelete.add(att);
                    //contentversionupdate.add(cv);
                 }
           }
            
        
//Insert the content versions from attachment data
            if(attachmentCVs.values().size() > 0 ) {
                insert attachmentCVs.values();
            }
                          
}
        ```
10
  • have a file extension is important which is used by apex to understand the file type and save it correctly. I can see title and path on the client both do not have a extension suffix. This may be an issue. try adding file ext you are trying to make
    – GirishP
    Jun 14 at 13:40
  • Hey @girish, thanks for helping out. I added '.pdf' to the Pathonclient only and it rendered correctly for the pdf even showing preview in files. However for doc,docx,rtf files (which are the rest of attachment types) they don't seem to produce any content in Salesforce files.
    – Kevin S
    Jun 14 at 18:03
  • Not sure if I'm giving the wrong extension in the PathOnClient, I've used .doc, .docx, and .rtf for the respective file types of the attachment. On another note, my Attachment.Name has the file extension in it's name itself thats why I was passing it directly as PathOnClient. In ContentVersion.Title I added the extension but it justs repeats the extension in the name as 'sample.doc.doc' so I guess title is fine but PathonClient is where its going wrong
    – Kevin S
    Jun 14 at 18:06
  • I think the file is just not previewable. have a look at the answer I have posted for details on limitations. ALternatively pls paste full code or link to playground so as to see which type of files are an issue for you
    – GirishP
    Jun 15 at 0:19
  • @GirishP, Hey Girish I've added my entire Trigger Helper for reference. The problem is not so much the Preview aspect but mainly because the content even after downloading is giving '1' or 'MQ==' in the document. Suprisingly PDF worked but the other 3 (doc,docx,rtf) not rendering anything even after downloading
    – Kevin S
    Jun 16 at 7:31
0

I don't see an issue with your code, as you have confirmed the pdf works just fine. As long as the PathOnClient or title has the ext Sf will convert it rightly.

However, there are few considerations for file preview features and not all are available to view online. You may have to download the file and view it to show all its data

Have a look at this developer guide. for detailed consideration https://help.salesforce.com/articleView?id=sf.content_preview.htm&type=5 https://help.salesforce.com/articleView?id=000337845&mode=1&sfdcIFrameOrigin=null&type=1

**Update Adding code based on the discussion above

trigger test on Attachment(after insert) {

public static void afterInsert(List<Attachment> attachinserted) {
    Set<ID> agreementset = New Set<ID>();
    List<ID> attachedIDs = New List<ID>();

    for (Attachment attach : attachinserted) {
        if (attach.ParentId.getSobjectType() == Account.SobjectType) {
            agreementset.add(attach.ParentId);
            attachedIDS.add(attach.Id);
        }
    }

     //Holds agreements with new Attachments
    List<Account> agreementAUS = [Select Id FROM Account WHERE ID IN:agreementset];

     //Holds attachments from correct Recordtypes
    List<Attachment> attachtoupdate = [
                                       SELECT Id,
                                       ParentId,
                                       Name,
                                       IsPrivate,
                                       Body,
                                       OwnerId,
                                       CreatedById,
                                       CreatedDate,
                                       ContentType,
                                       Description FROM Attachment WHERE ParentId IN:agreementAUS AND ID IN:attachedIDs
    ];

    //Conversion of Attachments into ContentVersions

     //map Attachment Id with ContentVersion record
    Map<Id,
        ContentVersion> attachmentCVs = new Map<Id,
                                                ContentVersion>();
    List<Attachment> attdelete = new List<Attachment>();
     //Map —> Attachment – Attachment Parent Id
    Map<Id,
        Id> attachmentParentIds = new Map<Id,
                                          Id>();
    List<ContentVersion> contentversionupdate = new List<ContentVersion>();

     //Generating file version using content version object
     //Set<Id> contentDocumentIdSet = new Set<Id>();
    if (!attachtoupdate.isEmpty()) {
        for (Attachment att : attachtoupdate) {
            ContentVersion cv = new ContentVersion();
            cv.ContentLocation = 'S';
            cv.PathOnClient = '/' + att.Name + '.doc';
            cv.Origin = 'H';
            cv.OwnerId = att.OwnerId;
            cv.Title = att.Name;
            cv.VersionData = att.body;
            cv.FirstPublishLocationId = att.ParentId;
            attachmentCVs.put(att.Id,
                              cv);
            attachmentParentIds.put(att.Id,
                                    att.ParentId);
            attdelete.add(att);
        }
    }
     //Insert the content versions from attachment data
    if (attachmentCVs.values().size() > 0) {
        insert attachmentCVs.values();
    }

}

}

3
  • Hey @Girish thanks for this code. It is working correctly now but I had to make an adjustment. Apparently the trigger after inserting the attachment couldn't recover the body quickly so I added the handler in a batch class which I called in a schedule job in the trigger for 1 minute later. And that seemed to do the trick finally. Thanks alot for your help.
    – Kevin S
    Jun 24 at 8:51
  • Really feels like a Heist job rather than a straightforward development use case.
    – Kevin S
    Jun 24 at 8:58
  • glad it helped. I guess the aptus package is first just creating an attachment and later updating the attachment with the body. just thinking based on what you suggested. Worth validating to save effort. of scheduling the batch as they are not guaranteed to run on time but when the resource are available. if this is not business critical batch is just fine for your use -case.else there is no obvious reason why would this behaviour happens. any case you solved your issue. :)
    – GirishP
    Jun 24 at 12:23

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.