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
NewToSitesCoolNewToSitesCool 

Chatter Photo API access

With the new API 20.0 version, seems like we get access to photos using SmallPhotoUrl and FullPhotoUrl, but seems like i need to have my salesforce session while accessing these images.

 

I have 2 requirements:

 

1. Way to download the image (get Image method)

2. Or an external shared image which can be accessed without salesforce session,

 

Is it possible with new API 20?

SuperfellSuperfell

You need a session to access them (but, then you needed a session to get the URLs from the User sobject, so you should have one, right?)

NewToSitesCoolNewToSitesCool

Not exactly i will have session because we want photos to go to external system, plan was to give External System URL for photo and that photo can then be directly accessed.

 

Any Ideas around how this can be done without session?

DanielJimenezDanielJimenez
I'm in the same boat here... Wish I could download the image.
DanielJimenezDanielJimenez
Is there maybe some way to pass in the SessionId that I received via the API a a query string param for the image?
cfahertycfaherty

Hi.  You need a 'sid=sessionid' cookie in your cookiestore for the salesforce.com domain to retrieve the user image.

DanielJimenezDanielJimenez
Interesting. Not sure I can do that from Javascript though because of xss security. Bummer.
cfahertycfaherty

I'm actually having a problem finding User.SmallPhotoUrl etc in API 20.  And the unsupported url (https://{instance}.salesforce.com/userphoto?id={ID}&v=1&s=T) for accessing photos is no longer working.

 

cfahertycfaherty

So.... is anyone else having a problem with User.SmallPhotoUrl et al in API 20?  It's supposed to be in production right?

DanielJimenezDanielJimenez
It returns a URL for me! Make sure you have your code set to run under API 20.0.
cfahertycfaherty

Are you using the Web API?

 

I'm using this as my endpoint but I'm not seeing the new fields in User:

https://login.salesforce.com/services/Soap/c/20.0

 

I will get a dump of my describe.

 

cfahertycfaherty

BTW mine is a developer account on na3 instance if that makes any diff.

cfahertycfaherty

After looking at a raw describeSObject(User) dump, I do in fact see the fields.  It's just one of my queries which is complaining, so let me go dig it up and go from there.

 

cfahertycfaherty

Just a follow up :-)

 

I can query User.SmallPhotoUrl and it works.

 

Here is the query I am having trouble with..

 

SELECT CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT 50


SoapFault - faultcode: 'sf:INVALID_FIELD' faultstring: 'INVALID_FIELD: 

SELECT CreatedBy.SmallPhotoUrl, CreatedDate

       ^

ERROR at Row:1:Column:8

No such column 'SmallPhotoUrl' on entity 'Name'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.'

I get this error:

 

SoapFault - faultcode: 'sf:INVALID_FIELD' faultstring: 'INVALID_FIELD:

SELECT CreatedBy.SmallPhotoUrl, CreatedDate

            ^

ERROR at Row:1:Column:8

No such column 'SmallPhotoUrl' on entity 'Name'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.'

 

cfahertycfaherty

I guess my problem is a misunderstanding of relationships.  From reading the docs I was under the impression that one could pull in any field via the relationship; i.e. CreatedBy.SmallPhotoUrl, CreatedBy.CompanyName etc.  I now see that this is not the case.

 

On an AccountFeed object, I am not understanding why CreatedBy.LastName works but CreatedBy.CompanyName does not.

 

I need to pull in the CreatedBy.SmallPhotoUrl along with my feed query, otherwise it will be expensive to deref a User object by Id to find the photo url.

 

DanielJimenezDanielJimenez
So anyone have any suggestions on how to get the user's profile image without the session cookie? My only thought is to build some kind of flash embed to work around the xss problem. Sure wish the photos could be publicly available though...
SFDeveloper999SFDeveloper999

I have seen the different urls for ProfilePhoto in Chatter Daily Digest. It is an HTML email displaying profile images of the user. Does any body know how these urls are getting generated? The images display properly without asking you to be login which means there must be some way to generate the publicly available user profile image.

Mattias NordinMattias Nordin

I also want to learn how to acces the profile photo. The old version worked fine even though you didnt get the last version of the photo.

 

If i just copy n paste the url for the picture it returns: https://flir.my.salesforce.com/profilephoto/7292000000004Kj/F

 

That link does not work. What to do???

SuperfellSuperfell

The link should work if you're logged in.

Mattias NordinMattias Nordin

Ahh... it does BUT the id string is no longer the user id. Im guessing it's the image object id.

 

I was hoping to accomplish something like below on a VF page.

 

<img align="left" src="https://xxx.my.salesforce.com/profilephoto/{!Opportunity.OwnerId}/F" style="border:1px solid #ccc;"/>

 

Any instructions on how to accomplish above.

 

THanks

 

PS im using the opportunity standard controller and was hoping that no extra coding was needed DS

<

 

apex:page standardController="Opportunity" sidebar="true" showHeader="true" >

SuperfellSuperfell

I think this should work.

 

<img align="left" src="{!Opportunity.Owner.FullPhotoUrl}" style="border:1px solid #ccc;"/>

Mattias NordinMattias Nordin

It would be perfect if that actually worked using the standard opportunity controller.

 

What do you have to do to get that to work? Using the standard controller i get an error message.

cfahertycfaherty
FWIW the photo urls are partial.
SuperfellSuperfell

What error message do you get ?

Mattias NordinMattias Nordin

Im getting "Save error: Invalid field FullPhotoUrl for SObject User" when i try to save my visual page to Sales Force.com using Eclipse.

 

This is the code i use on my visual force page. Before api 20 it was possible to show the picture this way.

 

<apex:page standardController="Opportunity" sidebar="true" showHeader="true" >

<table cellpadding="10" border="0" width="100%" style="font-size:16px;">
<tr>
<td>    
   <img align="left" src="{!Opportunity.Owner.FullPhotoUrl}" style="border:1px solid #ccc;"/>
</td>
<td>    
...
</td>
</tr>
</table>

</apex:page>

 

SuperfellSuperfell

Make sure your page is set to be api version 20.

cfahertycfaherty

 


potatoho wrote:

On an AccountFeed object, I am not understanding why CreatedBy.LastName works but CreatedBy.CompanyName does not.


It's because the CreatedBy relationship is for the Name object and not User.

 

Ergo


potatoho wrote:

SELECT CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT


becomes

SELECT CreatedBy.Profile.CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT

 

Abhinav GuptaAbhinav Gupta

This error is coming because "AccountFeed-> CreatedBy" can be either of reference type User or SelfServiceUser. In such cases a polymorphic object is returned on query. This polymorphic object is called "Name" and its having very limited fields as described here

cfahertycfaherty

Keep in mind though that the documentation is out of date.  The Name sobject has more fields than shown.  The Profile sobject has over 60 fields, and the documentation only shows 4.

 

Mattias NordinMattias Nordin

Thanks SimonF !

 

After updating Eclipse to api ver 20 and changing the xml file to version 20 it worked like a charm... thank you very much.

 

Im now using this syntax to display the photo:

 

 

 

<

apex:page standardController="Opportunity" sidebar="true" showHeader="true" >

...

<img align="left" src="{!Opportunity.Owner.FullPhotoUrl}" style="border:1px solid #ccc;"/>

cfahertycfaherty

 

Heads up. I've seen a change in the SmallPhotoUrl as of 2/11/11. It's now a complete URL (including https etc) rather than a relative URL. Also it is going to a force.com domain for the photos rather than salesforce.com so you must adjust your cookie jar accordingly. Unfortunately I haven't figured out how to make the new photo URLs work, as my original setting of sid= within the cookie jar is not working and I am getting a null response back from the new photo URLs.

 

cfahertycfaherty

Okay I got it working today.

 

Prior to 2/11/11 you set a sid cookie for .salesforce.com domain. Used the smallPhotoUrl as a relative Url to your API Url.

 

Post 2/11/11 you set a sid cookie for c.%s.content.force.com domain, where %s is your instance which you can parse from your server Url. Remove the "-api" from it; i.e. na3-api, you use na3 as in c.na3.content.force.com for the cookie domain.

 

Then you must allow circular redirects in your client because it goes off and authenticates and then comes back to the same photo Url. Set the max redirect to 3.

 

For example, using HttpClient..

 

HttpParams params = new BasicHttpParams();

params.setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
params.setIntParameter(ClientPNames.MAX_REDIRECTS, 3);

 

DefaultHttpClient httpclient = new DefaultHttpClient(manager, params);

 

cfahertycfaherty

I should also mention this..

 

http://stackoverflow.com/questions/2172752/httpsurlconnection-and-intermittent-connections

 

In using Android I was having very slow image retrieval using HttpClient on some devices. I began using getThreadSafeHttpClient() from that post and it brought the performance back. I'm not sure which param was causing the issue but without it I was seeing an SSL reset upon every image retrieval.

 

cfahertycfaherty

 


potatoho wrote:

Post 2/11/11 you set a sid cookie for c.%s.content.force.com domain, where %s is your instance which you can parse from your server Url. Remove the "-api" from it; i.e. na3-api, you use na3 as in c.na3.content.force.com for the cookie domain.

 

Then you must allow circular redirects in your client because it goes off and authenticates and then comes back to the same photo Url. Set the max redirect to 3.

 


I just found a bug in my code whereby I was submitting a bogus sid on the first request. It turns out that a valid sid in the .salesforce.com domain is fine with the new photo url requests. No circular redirect or .force.com cookie necessary.

 

DanielJimenezDanielJimenez
Has anyone figured out how to deduce the url for the chatter photos that is used in the digest emails? For example, the link to my "avatar" is: https://na7.salesforce.com/ncsphoto/koHHGBTTJTmbb_Cy7U3iVK9jrWQ9s6BqhROh2hVv-7B-eZPOpF4peVqSZesLJu-y I'm not sure what ncsphoto means, but it would be great if we could just use these urls.
cfahertycfaherty

That is interesting, in that there doesn't appear to be the need for a sessionid. I can't make rhyme out of the ncsphoto url either. I did notice one thing yesterday when I was implementing the identity url.

 

Check https://na3.salesforce.com/help/doc/en/remoteaccess_using_openid.htm

 

You see that there is a "photos" section there with the full and thumbnail of the user. I don't have a response handy, but I don't believe it was the ncsphoto url.

 

cfahertycfaherty

I do have something else critical to add regarding sessionid. This goes along with my post from yesterday:

 

http://boards.developerforce.com/t5/Security/OAuth-2-0-User-Agent-Flow-token-and-SFDC-UI/td-p/248131

 

An OAuth2 access_token (used as sessionid) cannot be used to authenticate photo url requests, which hinders the ability of a third-party Chatter application to use OAuth.

 

jwoodall1jwoodall1

cfaherty, did you find out how this relationship with the user table worked?

 

SELECT CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT 50

 

I haven't found a way to get the SmallPhotoUrl from people on the feed, only the user logged in.  I've tried:

 

NewsFeed.User.SmallPhotoUrl

FeedItemNewsFeed.User.SmallPhotoUrl

FeedItem.User.SmallPhotoUrl

CreatedBy.User.SmallPhotoUrl

 

and some others with no luck.

cfahertycfaherty

jwoodall1 wrote:

cfaherty, did you find out how this relationship with the user table worked?

 

SELECT CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT 50

 

I haven't found a way to get the SmallPhotoUrl from people on the feed, only the user logged in.  I've tried:

 

NewsFeed.User.SmallPhotoUrl

FeedItemNewsFeed.User.SmallPhotoUrl

FeedItem.User.SmallPhotoUrl

CreatedBy.User.SmallPhotoUrl

 

and some others with no luck.


Yes, like this..

 

SELECT CreatedBy.Profile.CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT

 

 

jwoodall1jwoodall1

Thanks for the reply cfaherty.  The problem is that returns the Photo of the person who created the user's profile, not the person that created the post.  Here's my full query.

 

SELECT CreatedBy.Profile.CreatedBy.SmallPhotoUrl, CreatedBy.Profile.CreatedBy.LastName, Id, Type,
                                CreatedById, CreatedBy.FirstName, CreatedBy.LastName, CreatedDate,
                                ParentId, Parent.Name,
                                    Body, Title, LinkUrl,
                                (SELECT Id, FieldName, OldValue, NewValue
                                          FROM FeedTrackedChanges ORDER BY Id DESC),
                                (SELECT Id, CommentBody, CreatedDate,
                                        CreatedById, CreatedBy.FirstName, CreatedBy.LastName
                                        FROM FeedComments ORDER BY CreatedDate DESC, ID DESC LIMIT 10),
                                (SELECT CreatedBy.FirstName, CreatedBy.LastName FROM FeedLikes)
                                 FROM NewsFeed WHERE ParentId = :ApexPages.currentPage().getParameters().get('id')
                                 ORDER BY CreatedDate DESC, ID DESC
                                 LIMIT 10

cfahertycfaherty

I guess we both need a solution then.  Bummer.

 

The NewsFeed.CreatedBy is a reference to a Name object, which is often used as a placeholder for polymorphic fields if I remember correctly. I think you'd have to see if there is some other relationship within Name which can be followed.

 

Why'd they make this so hard?

 

freynoldsfreynolds

cfaherty wrote:

 


potatoho wrote:

On an AccountFeed object, I am not understanding why CreatedBy.LastName works but CreatedBy.CompanyName does not.


It's because the CreatedBy relationship is for the Name object and not User.

 

Ergo


potatoho wrote:

SELECT CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT


becomes

SELECT CreatedBy.Profile.CreatedBy.SmallPhotoUrl, CreatedDate, FeedPost.Body, Id, CreatedBy.Name, CreatedById FROM AccountFeed WHERE (ParentId = '0015000000TIHa4AAH') ORDER BY CreatedDate ASC LIMIT

 


THANK YOU SO MUCH, SO SO MUCH

Ashish_NarangAshish_Narang
There seems to be some option added in v28.0. standardEmail​PhotoUrl field is available in ConnectApi.Photo Class

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_connectapi_output_photo.htm
 
robert wood 12robert wood 12
I had faced the same problem. The Utah family photographer shows the way to download the image.