+ Start a Discussion
Harry DhanoaHarry Dhanoa 

Updating a Chatter FeedItem

Hi,

I wrote a custom button that call a class to insert a pdf in chatter feed of a Custom Object.

This was successfully done with the code snippet below:-

 

global class  ImportFileToSF { 

  Webservice static String  uploadPDF(Id testId) { 

    Boolean isAnUpdate = false;

    Http h = new Http(); 

    HttpRequest req = new HttpRequest(); 

    string url = 'http://www.salesforce.com/us/developer/docs/daas/salesforce_migration_guide.pdf'

    url = url.replace(' ', '%20'); req.setEndpoint(url); 

    req.setMethod('GET'); 

    req.setHeader('Content-Type', 'application/pdf;'); 

    req.setCompressed(true); 

    req.setTimeout(120000); 

    HttpResponse res = null

    res = h.send(req); 

    blob file = res.getBodyAsBlob(); 

    blob oldFile = null;

  

    FeedItem post = new FeedItem();

    post.ParentId = testId;

    post.ContentData = file;

    post.ContentFileName = 'SF migration.pdf';

    post.CreatedById = '005E0000000i4VFIAY';

    post.Type='ContentPost';

    post.Visibility = 'AllUsers';

    

    insert post;

  }    

}

Now the requirement is when I click the button again a new version of that document should be inserted.

Could some one give me a code snippet that does the job?

 

Best Answer chosen by Admin (Salesforce Developers) 
Harry DhanoaHarry Dhanoa

Nailed it.

Here is the code that does the magic.

global class  ImportFileToSF { 
  Webservice static String  uploadPDF(Id testId, Id userId) { 
	try {  
	    //Http request to fetch the pdf
	    Http h = new Http(); 
	    HttpRequest req = new HttpRequest(); 
	    string url = 'http://www.salesforce.com/us/developer/docs/daas/salesforce_migration_guide.pdf'; 
	    url = url.replace(' ', '%20'); req.setEndpoint(url); 
	    req.setMethod('GET'); 
	    req.setHeader('Content-Type', 'application/pdf;'); 
	    req.setCompressed(true); 
	    req.setTimeout(120000); 
	    HttpResponse res = null; 
	    res = h.send(req);     
	    blob file = res.getBodyAsBlob();	    
	    FeedItem[] fI = [Select RelatedRecordId from FeedItem where ParentId = :testId];
	     
		//This statement checks if the button should add the first version to the object
		//else add the subsequent versions 
		if(fI.size() > 0) {
			ContentVersion content = new ContentVersion();
			content.versionData = file;
			content.title = 'SF migration1.pdf';
			content.pathOnClient = 'SF migration1.pdf';
			content.ContentDocumentId = [Select ContentDocumentId from ContentVersion where id=:fI[0].RelatedRecordId].ContentDocumentId; 
			insert content;					
		} else {
		    FeedItem post = new FeedItem();
		    post.ParentId = testId;
		    post.ContentData = file;
		    post.ContentFileName = 'SF migration.pdf';
		    post.CreatedById = userId;
		    post.Type='ContentPost';
		    post.Visibility = 'AllUsers';		
		    insert post;
		}	
	} catch(Exception e) {
    	return 'The following exception has occurred: ' + e.getMessage();
	}	    
    return '1';
  }     
}

 

Seems like adding the ContentDocumentId to ContentVersion did the magic.

So the gist is:-

Insert a Chatter Feed document by inserting a FeedItem

In order to update a new version create a new ContentVersion.

 

Thanks for your help sq.

All Answers

Harry DhanoaHarry Dhanoa

Thanks for looking into it SQ.
I have already looked into that option and am attaching along the steps to reproduce the following error:-

error : {faultcode:'soapenv:Client', faultstring:'System.DmlException: Insert failed. First exception on row 0; first error: INVALID_FIELD, Feed posts containing Content must be of type ContentPost: [Type]
Class.ImportFileToSF.uploadPDF: line 37, column 1', }

 

I created an object called Test and created a custom button on it with the following Behavoiur - 'Execute Javascript' ContentSource - Onclick Javascript

 

{!REQUIRESCRIPT("/soap/ajax/15.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/15.0/apex.js")}

try{
    var retval = sforce.apex.execute("ImportFileToSF", "uploadPDF", {testId:'{! Test__c.Id }', userId:sforce.connection.getUserInfo().userId });
    window.location.reload();
}catch(e){
    alert('error : ' + e);
}

 

 

Also created the class:-

 

global class  ImportFileToSF {
  Webservice static String  uploadPDF(Id testId, Id userId) {
    
    //Http request to fetch the pdf
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    string url = 'http://www.salesforce.com/us/developer/docs/daas/salesforce_migration_guide.pdf';
    url = url.replace(' ', '%20'); req.setEndpoint(url);
    req.setMethod('GET');
    req.setHeader('Content-Type', 'application/pdf;');
    req.setCompressed(true);
    req.setTimeout(120000);
    HttpResponse res = null;
    res = h.send(req);     
    blob file = res.getBodyAsBlob();
     
    //This statement checks if the button should add the first version to the object
    //else add the subsequent versions
    if([Select count() from FeedItem where ParentId = :testId] > 0) {
        ContentVersion content = new ContentVersion();
        content.versionData = file;
        content.title = 'SF migration1.pdf';
        content.pathOnClient = 'SF migration1.pdf';
        //content.origin = 'H';
        
        insert content;
        
        FeedItem post = new FeedItem();
        post.ParentId = testId;
        post.ContentData = file;
        post.ContentFileName = 'SF migration.pdf';
        post.CreatedById = userId;
        post.Type='TrackedChange';
        post.Visibility = 'AllUsers';
        post.ParentId = [Select ContentDocumentId from ContentVersion where id=:content.Id].ContentDocumentId;
        
        insert post;
                
    } else {
        FeedItem post = new FeedItem();
        post.ParentId = testId;
        post.ContentData = file;
        post.ContentFileName = 'SF migration.pdf';
        post.CreatedById = userId;
        post.Type='ContentPost';
        post.Visibility = 'AllUsers';
    
        insert post;
    }        
    return '1';
  }     
}

 

Add Security Controls--> Remote Site Settings--> New Remote Site  --> URL (http://www.salesforce.com)

App Setup > Customize > Salesforce CRM Content > Settings > Enable Salesforce CRM Content

 

SimplySfdcSimplySfdc

What is line 37 in the apex class?

I assume insert to FeedItem has no issue.

Harry DhanoaHarry Dhanoa

Unfortunately, it is the insert to FeedItem where the issue lies.

Line 37 is marked in red below:-

 

        post.ParentId = [Select ContentDocumentId from ContentVersion where id=:content.Id].ContentDocumentId; 
        
        insert post;
                
    } else {

SimplySfdcSimplySfdc

What is the purpose of

post.ParentId = [Select ContentDocumentId from ContentVersion where id=:content.Id].ContentDocumentId; 

 

I do not see you can use ContentVersion as FeedItem parent 

Harry DhanoaHarry Dhanoa

 

Seems like the field ParentId can contain the object Id (Test__c.Id) or ContentDcument Id.

Am not using ContentVersion as the post.ParentId but ContentDocument's Id.

 

I gathered the SOQL results by uploading and then updating it's version from standard SF:-

 

Uploaded file "Version1.png" from standard SF front end                
Fields                      record1    
ContentFileName    version1.png            
ContentSize            18854            
ContentType            image/png            
ParentId                   a0cE000000Baue7IAB            
RelatedRecordId     068E0000001IvYDIA0            
Title                          version1            
Type                         ContentPost            
Visibility                    InternalUsers            
                
Updated "Version1.png" by uploading "Version2.png" from standard SF front end                
Fields                      record1                           record2
ContentFileName    version2.png            
ContentSize            32532                             0        
ContentType           image/png            
ParentId                  a0cE000000Baue7IAB   069E0000001EJNjIAO        
RelatedRecordId    068E0000001IvYDIA0            
Title                        version2            
Type                       ContentPost                    TrackedChange        
Visibility                  InternalUsers                   AllUsers                                           

 

 

* ContentVersion Id's --> 068......

*ContentDocument Id's --> 069.....          

SimplySfdcSimplySfdc

Can you debug if query 

post.ParentId = [Select ContentDocumentId from ContentVersion where id=:content.Id].ContentDocumentId; 

return correct Id ?

Harry DhanoaHarry Dhanoa

       

I added a debug statement as below:-

 

.......

        post.Visibility = 'AllUsers';
        post.ParentId = [Select ContentDocumentId from ContentVersion where id=:content.Id].ContentDocumentId;
        system.debug(' post.ParentId >>'+post.ParentId);
        
        insert post;
                
    } else {
        FeedItem post = new FeedItem();

.......

 

The debug log is:-

 

14:24:20.078 (2078464518)|SYSTEM_METHOD_EXIT|[36]|String.valueOf(Object)
14:24:20.078 (2078481474)|SYSTEM_METHOD_ENTRY|[36]|System.debug(ANY)
14:24:20.078 (2078487765)|USER_DEBUG|[36]|DEBUG| post.ParentId >>069E0000001EJQOIA4
14:24:20.078 (2078491453)|SYSTEM_METHOD_EXIT|[36]|System.debug(ANY)
14:24:20.078 (2078515196)|DML_BEGIN|[38]|Op:Insert|Type:FeedItem|Rows:1

                                   

SimplySfdcSimplySfdc

Random thought, how ContentVersion record created ?

Harry DhanoaHarry Dhanoa

 

Since it is throwing an error message it is not.

Once I comment out the line "insert post;" it successfully does.

 

Harry DhanoaHarry Dhanoa

Nailed it.

Here is the code that does the magic.

global class  ImportFileToSF { 
  Webservice static String  uploadPDF(Id testId, Id userId) { 
	try {  
	    //Http request to fetch the pdf
	    Http h = new Http(); 
	    HttpRequest req = new HttpRequest(); 
	    string url = 'http://www.salesforce.com/us/developer/docs/daas/salesforce_migration_guide.pdf'; 
	    url = url.replace(' ', '%20'); req.setEndpoint(url); 
	    req.setMethod('GET'); 
	    req.setHeader('Content-Type', 'application/pdf;'); 
	    req.setCompressed(true); 
	    req.setTimeout(120000); 
	    HttpResponse res = null; 
	    res = h.send(req);     
	    blob file = res.getBodyAsBlob();	    
	    FeedItem[] fI = [Select RelatedRecordId from FeedItem where ParentId = :testId];
	     
		//This statement checks if the button should add the first version to the object
		//else add the subsequent versions 
		if(fI.size() > 0) {
			ContentVersion content = new ContentVersion();
			content.versionData = file;
			content.title = 'SF migration1.pdf';
			content.pathOnClient = 'SF migration1.pdf';
			content.ContentDocumentId = [Select ContentDocumentId from ContentVersion where id=:fI[0].RelatedRecordId].ContentDocumentId; 
			insert content;					
		} else {
		    FeedItem post = new FeedItem();
		    post.ParentId = testId;
		    post.ContentData = file;
		    post.ContentFileName = 'SF migration.pdf';
		    post.CreatedById = userId;
		    post.Type='ContentPost';
		    post.Visibility = 'AllUsers';		
		    insert post;
		}	
	} catch(Exception e) {
    	return 'The following exception has occurred: ' + e.getMessage();
	}	    
    return '1';
  }     
}

 

Seems like adding the ContentDocumentId to ContentVersion did the magic.

So the gist is:-

Insert a Chatter Feed document by inserting a FeedItem

In order to update a new version create a new ContentVersion.

 

Thanks for your help sq.

This was selected as the best answer
SimplySfdcSimplySfdc

Vanjara, 

so you not insert FeedItem anymore when upload new version of file?

just insert ContentVersion?