I have a project to upload some files for both licensed users and portal users. Got it working 98%... except for portal users.. mama mia...

I created a site off a domain, logged in a user and inserted a ContentVersion by API, and also an Attachment, both in JavaScript, and the ContentVersion appears in salesforce classic chatter, and the attachment in an account related list. However, ideally, I want to insert just Attachments, but when setting Parent Id in JavaScript, an exception is thrown using the API for portal users: Attachment: Bad Field names on insert/update call: ParentId.

I read recently that API calls are now restricted for attachments, and we cannot insert attachments for portal users, as witnessed by the exception. Is there some way I can let a portal user upload an attachment so a ParentId can be set? (In my case, set to an account record.) Need I try sending attachments as an email and make a trigger on emails received to insert an attachment?

Function UploadFile(parentId) is called from an onclick commandlink. variables {!sessionID} {!username} {!password} and {!parentAccountName} are set in prior pages. The !sessionID is a session ID generated by logging in on a prior page using SOAP, but when I get to here and try to insert, error says session invalid, so I've logged in on this page too, but using the API to get a session... If a local user is using my forms, no problems, meaning not required to login to API AND I can insert an attachment like I like instead of inserting a VersionContent.

<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="/soap/ajax/32.0/connection.js" type="text/javascript"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>

<script type="text/javascript">
            localUsersession = '{!$Api.Session_ID}', externalUsersession = '{!sessionID}';
                var filesToUpload = [];  
                var uploadedFile = 0, __sfdcSessionId='', runninglog='';

            if ( (localUsersession=='') || (localUsersession=='NULL_SESSION_ID')) { 
                    sforce.connection.login('{!username}','{!password}');  // username and password come from the controller, set in the login page
            else {
                    sforce.connection.sessionId = __sfdcSessionId;

        function uploadFile(parentId)
                // parentId='001o000000Pc7HtAAJ'; // for debugging

                 for(var i = 0, f; f = filesToUpload[i]; i++)

                    var reader = new FileReader();

                    // Keep a reference to the File in the FileReader so it can be accessed in callbacks
                    reader.file = f;

                    reader.onload = function(e)
                       /* this block is for attachment insertion

                        var att = new sforce.SObject("Attachment");
                        att.Name = this.file.name;
                        att.ContentType = this.file.type;
                        att.ParentId = parentId;

                        var binary = "", bytes = new Uint8Array(e.target.result);
                        var length = bytes.byteLength;

                        for (var j = 0; j < length; j++)
                            { binary += String.fromCharCode(bytes[j]); }

                        att.Body = (new sforce.Base64Binary(binary)).toString();


                           var fi = new sforce.SObject('FeedItem'); 
                               fa = new sforce.SObject('FeedAttachment');
                               cv = new sforce.SObject('ContentVersion');

                            fi.Title = this.file.name;
                            fi.Body = 'Document from '+'{!nickname}';
                            fi.ParentId = parentId;

                            cv.Title=this.file.name+' for: '+{!parentAccountName};
                            cv.VersionData = (new sforce.Base64Binary(binary)).toString();
                            cv.PathOnClient= this.file.name;

                            onSuccess : function(result, source)
                                if (result[0].getBoolean("success"))
                                  fa.FeedEntityId = fi.Id;
                                  fa.RecordId = cv.Id;
                                  fa.Title='Document from {!nickname}';

                                  var  html = "Finished uploading "+att.Name; 
                                      if (filesToUpload.length>1)  
                                        html+='... Now uploading the next one...';
                                  document.getElementById('statusid').innerHTML = html;

                                } // success
                                {   var html = "Failed to create attachment!<br/>"+result[0];
                                    document.getElementById('statusid').innerHTML = html;

                            onFailure : function(error, source)
                                var html = "An Error has occurred<br/>"+error;
                                document.getElementById('statusid').innerHTML = html;


                        }); // sforce.create feeditem 
                        } // externalUsersession
                        { etc... repeat the onsuccess and onfailure blocks


        }  // onload
        } // for loop
    } // function uploadfiles
  • 1
    Can you share your code you have written so far? Commented Aug 25, 2017 at 13:55

1 Answer 1


Wrestling with this has led me to use up 1 Salesforce license to do the uploads for a "chatter free" user. So I made a user account called portal attachment, so when I log in to the API with that it uploads fine. So the problem is Salesforce doesn't let users with a chatter free profile to create an attachment. And all this is really strange.. I suppose they really want us using communities instead of portals... $$$ :-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .