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
dwwrightdwwright 

Display Attachment Names Before Inserting Them

I'm trying to create a page that allows my users to fill in fields, attach as many files as they want, and then submit the information, creating a new lead with all the attachments.

 

What I want to do is let the user attach files BEFORE submitting, meaning BEFORE the Lead is actually inserted into the database. To try to accomplish this, I'm creating a list of attachments in the controller and then holding the attachments there. When the user clicks "submit" I then insert the Lead and assign all of the attachments in the list to that Lead.

 

The goal here is to be able to submit the Lead and its Attachments at the same time.

 

I'm hitting the viewstate size limit (I'm growing to dislike that error very much.) Is there a way to efficiently gather attachments before inserting them into the DB? Below are my relevant code snippets:

 

 

public class newLeadExtension {

public Lead theLead;
public String theName {get; set;}
public Attachment att {get; private set;} //Holds value from inputFile
public List<Attachment> attachments {get; set;} //Holds attachments
public List<String> attachmentNames {get; set;} //Holds atachment names

//Get the lead from the standardcontroller
public newLeadExtension(ApexPages.StandardController cont) {
theLead = (Lead)cont.getRecord();
att = new Attachment();
attachmentNames = new List<String>();
attachments = new List<Attachment>();
}

public PageReference attach() {
attachments.add(att);
attachmentNames.add(att.Name);
return null;
}
}

 

Attach A File:<br/>
<apex:inputFile value="{!att.Body}" filename="{!att.Name}" />
<apex:commandButton value="Attach" action="{!attach}"/>

Attached Files:<br/>
<apex:repeat var="att" value="{!attachmentNames}" >
&nbsp;&nbsp;{!att}<br/>
</apex:repeat>

 

 

(The "submit" method isn't shown here, but it just inserts the lead, then iterates through the attachment list assigning each parent ID as the lead and inserting it)

 

Thanks for any help you can provide!

Best Answer chosen by Admin (Salesforce Developers) 
AvromAvrom

There's no easy way to do this--you can't store the attachments as part of the view state, because that would invole making each request/response *huge*.

 

One thing you could try is to create a special custom object just to hold temporary attachments, and to actually save that custom object on each request. On "real" save, you'd then move the attachments to the Lead.

 

You'd probably want to write some batch Apex to periodically clear out residual custom objects and their attachments (those left over from abandoned sessions and the like).

 

All Answers

Shailesh DeshpandeShailesh Deshpande

try n make the attachment list transient....

 

public transient List<Attachment> attachments {get; set;}	//Holds attachments

 

I hope this helps.

dwwrightdwwright

I tried that already... I get an exception: "Attemp to de-reference a null object" =\

AvromAvrom

There's no easy way to do this--you can't store the attachments as part of the view state, because that would invole making each request/response *huge*.

 

One thing you could try is to create a special custom object just to hold temporary attachments, and to actually save that custom object on each request. On "real" save, you'd then move the attachments to the Lead.

 

You'd probably want to write some batch Apex to periodically clear out residual custom objects and their attachments (those left over from abandoned sessions and the like).

 

This was selected as the best answer
ahab1372ahab1372

on what line do you get the error? I still think transient is the way to go.

 

Have you tried removing the get and set from the attachmens lList variable? Since you are not referencing the attachments list on your VF page, you don't need get/set..

 

Also, try to set the att variable  to Null after upoading a new attachment and adding it to the list. Maybe returning a single attachment in the new view state is already too much.

 

 

AvromAvrom

You can't set this to transient if you're trying to persist it across requests without a save.

 

That's what "transient" means--throw the value away with each request and start over. If the list of attachments is marked as transient, it won't be maintained from request to request (unless you actually save it in some way, which is what I suggested). That's where the "attempt to dereference a null object" error is coming from--on subsequent requests, the transient list is null.

 

While its conceivable that a single attachment in a non-transient variable will exceed the view state limit, I think it's rather more likely, in this case, that the limit was broken because of the attempt to add multiple attachments to a non-transient variable, since that's what's unusual about the case.

 

ahab1372ahab1372

I ran into a similar problem with a single PDF blob (about 280KB) that is attached to an email (and inserted as attachment) from a VF page. Transient worked for me because the blob was created again when necessary without the user having to do "all the work" again.. I see that it does not work in this scenario.

 

Saving them temporarily as a custom object sounds like a good idea. Thanks for the feedback

 

 

dwwrightdwwright

Thanks for the response guys--I know now not to bang my head against the wall trying to get this to work the way I've been trying.