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? Aug 25 '17 at 13:55

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... $$$ :-)

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.