I am trying to upload a file from salesforce sites into Files and then relate it with a record using VF page.

i am able to upload the file and while creating a ContentDocumentLink i am getting this error.

Document: You don't have permission to share this file.

insert file; 
                    ContentVersion cv = [SELECT id, ContentDocumentId FROM ContentVersion where Id = :file.Id];
                    ContentDocumentLink link = new ContentDocumentLink();
                    link.LinkedEntityId = sr.id; // this is record i want the file to be related to 
                    link.ContentDocumentId = cv.contentdocumentid;
                    link.ShareType = 'V';
                    link.Visibility = 'AllUsers';
                    insert link;

Since the user who uploads the file is a site guest user, i am assuming thats the reason why i am getting this error.

Is there a way we can allow creation of ContentDocumentLink for site guest user? What i want is a way to associate the uploaded file with a record

5 Answers 5


Make sure that your guest site users has sharing record access to the entity the file is being shared with. I did a POC with a visualforce page exposed to public site and the guest user was able to create an account and upload a file to it without error.

Apex Controller

public class UploadDocumentDemoController {

// placeholder to upload files from visualforce page with
public Attachment file { get; set; }

public UploadDocumentDemoController() {
    this.file = new Attachment();

public void save() {

    System.debug( 'Saving document' );

    System.debug( file );

    // for proof of concept, will create one account for testing purposes
    // and each time we submit the form to upload file we don't create more and more accounts
    ID accountId = null;
    List<Account> accounts = [ SELECT id FROM Account WHERE name = :UserInfo.getUserId() LIMIT 1 ];
    if ( accounts.size() == 0 ) {
        Account acct = new Account(
            name = UserInfo.getUserId()
        insert acct;
        accountId = acct.id;
    } else {
        accountId = accounts[0].id;

    // create the chatter file
    ContentVersion cv = new ContentVersion(
        versionData = file.body,
        title = file.name,
        pathOnClient = '/' + file.name

    insert cv;

    // look up the content document id
    cv = [ SELECT id, ownerId, contentDocumentId FROM ContentVersion WHERE id = :cv.id ];

    // link the document to the account
    ContentDocumentLink cdl = new ContentDocumentLink(
        linkedEntityId = accountId,
        contentDocumentId = cv.contentDocumentId,
        shareType = 'V',
        visibility = 'AllUsers'

    insert cdl;



Visualforce Page

<apex:page controller="UploadDocumentDemoController" cache="false">



            <apex:commandButton action="{!save}" value="Upload"/>

        <apex:pageBlockSection columns="1">
            <apex:inputFile value="{!file.body}" fileName="{!file.name}"/>



  • Thanks Doug.. i get the same error which makes me believe there is something on my guest user profile which is restricting access.
    – Prady
    Aug 29, 2016 at 6:40
  • Did you by any chance add any library permissions or any other permissions for guest user? Did you test it as a site user?
    – Prady
    Aug 29, 2016 at 6:49
  • i did run my code and your code from within salesforce and not from sites. They seem to save the file and link it to associated records. But when run from sites they fail
    – Prady
    Aug 29, 2016 at 6:58
  • Hi Prady, the only change to the Public Guest profile was that I made sure it had Read/Create access to Accounts and Contacts objects and Read/Edit on those object fields. I added that visualforce page as available to the Site. But other than that, no other tweaks.
    – Doug Ayers
    Aug 29, 2016 at 16:39
  • Strange.. i also have Read/Create Access to Accounts and contacts and also Read and Edit access to the fields. I am creating a contact record and trying to relate the file to this contact.
    – Prady
    Aug 30, 2016 at 17:08

I ended up doing apex callout from site vf page's controller to apex REST Webservice using Connected App - API User. It works perfectly in my customer's sandbox, hope it is helpful to someone!!!


Quickly tried Ronnie's answer to see if this was that easy, but didn't workout and received the below error.

Reverted it back to my apex callout from site vf page's controller to apex REST Webservice using Connected App - API User. It works!


Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, You don't have permission to share this file.: [ContentDocumentId]


private without sharing class MyAdminProcesses{

      id decodedID{ get; set; }
      string cvId{ get; set; }
      ContentDocumentLink cdl { get; set; }

      public MyAdminProcesses( string decodedID, string cvId){
          cdl = new ContentDocumentLink();
             cdl.ContentDocumentId = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id =: cvId].ContentDocumentId;
             cdl.LinkedEntityId = decodedID;
             cdl.ShareType = 'V';
             cdl.Visibility = 'AllUsers';

      public void DoMyFileSharingChanges(){
          insert cdl;


MyAdminProcesses admin = new MyAdminProcesses( decodedID, cvId );

I had a similar issue, contacted Salesforce support, and we discovered that it wouldn't work in a Community site, but would work in a Force.com site, the support person basically said that since Guest Users are not members of the Community, it will not allow them to upload any files in the Community.

Perhaps that explains why some people have the problem and others don't?

I was able to get my page to work and also the sample one suggested by Doug above in the Force.com site, but not in the Community site.


If this is something that you want to do for every upload from the SiteGuestUser you can simply add an inner class that executes without sharing for this item and handle the tasks as admin user.

public with sharing class MyPublicController{

     public void myUploadMethod(){

         MyAdminProcesses admin = new MyAdminProcesses( data );


     private without sharing class MyAdminProcesses{

          Object myFileData { get; set; }

          public MyAdminProcesses( Object myFile ){
              myFileData = myFile;

          public void DoMyFileSharingChanges(){


I do not see why this shouldn't work for your case here. It appears to me that you want to treat these uploads from public site as a general type for all and share them with this sObject that you have.

You must log in to answer this question.

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