Right now, the code below upon submit, first inserts a file THEN submits the form. This is problematic - I need for it to verify the form was successfully posted to Amazon S3 then insert the (token) file so it can link to it.
I basically need to reverse SubmitFile and InsertFile, but I'm not sure how to have (If form successfully sent, then run another javascript function). See very bottom for an attempt...Is this possible?
<apex:pageMessages id="pageErrors"></apex:pageMessages>
<form name="s3Form" action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="key"/>
<input type="hidden" name="AWSAccessKeyId" value="{!key}"/>
<input type="hidden" name="policy" value="{!policy}"/>
<input type="hidden" name="signature" value="{!signedPolicy}"/>
<input type="hidden" name="acl" value="private"/>
<input type="hidden" name="x-amz-meta-FileId" value="{!File__c.id}"/>
<input type="hidden" name="x-amz-meta-OrderId" value="{!OrderId}"/>
<input type="hidden" name="x-amz-meta-CustomerId" value="{!CustomerId}"/>
<input type="hidden" name="success_action_redirect" value="{!serverUrl}{!OrderId}"/>
<apex:pageBlock title="New File Upload" mode="maindetail" tabStyle="File__c"> <!-- rendered="{!open}"-->
<apex:pageBlockSection title="File Information" columns="2" collapsible="false" showHeader="false">
<apex:pageBlockSectionItem >
<apex:outputLabel value="Select File" for="selectFile"/>
<input id="selectedFile" type="file" size="25" name="file" onChange="setFileName(this.value)"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<apex:pageBlockButtons location="bottom">
<input class="btn" type="button" value="Upload File" onClick="checkFile();return false;"/>
<input class="btn" type="button" value="Cancel" onClick="cancelFile();return false;"/>
<input class="btn" type="button" value="Complete Order" onClick="pleteFile();return false;"/>
</apex:pageBlockButtons>
</apex:pageBlock>
<apex:outputText styleClass="footer" value="Please click Complete Order when all the required files are uploaded. Thank you." />
</form>
<apex:form id="sfForm"><!-- rendered="{!open}"-->
<apex:inputHidden id="hiddenServerURL" value="{!serverURL}"/>
<apex:inputHidden id="fileName" value="{!fileName}"/>
<apex:inputHidden id="contentType" value="{!contentType}"/>
<apex:inputHidden id="fileType" value="{!fileType}"/>
<apex:actionFunction name="insertFile" action="{!insertFile}" onplete="submitFile();return false;"/>
<apex:actionFunction name="pleteOrder" action="{!pleteOrder}"/>
<script type="text/javascript">
var sendFile = false;
document.getElementById('{!$Component.hiddenServerURL}').value = '{!$Api.Enterprise_Server_URL_140}';
function setFileName(file) {
var f = file.replace(/\\/g, "");
f = f.replace(/C\:fakepath/g, ""); <!--Required for IE8-->
document.s3Form.key.value = "{!CustomerName}/{!OrderName}/" + f;
document.getElementById('{!$Component.fileName}').value = f;
suffix = f.lastIndexOf(".") + 1;
contentType = f.slice(suffix);
document.getElementById('{!$Component.contentType}').value = contentType;
}
function setFileType(type) {
document.getElementById('{!$Component.fileType}').value = type;
}
function checkFile() {
if (document.s3Form.file.value=="") {
alert("Please, select a file.");
return false;
}
else if (document.s3Form.fType.value=="--None--") {
alert("Please, select a file type.");
return false;
}
else {
alert("Uploading...Please click OK and wait for page to refresh.");
insertFile();
sendFile = true;
}
}
function submitFile() {
if(sendFile = false) {
return false;
}
else {
document.s3Form.submit();
}
}
function pleteFile() {
pleteOrder();
}
</script>
</apex:form>
In the controller (extension):
//SF File insert on an object (passed from page)
public PageReference insertFile() {
this.file.Name = fileName;
this.file.Type__c = fileType;
this.file.Content__c = contentType;
insert this.file;
return null;
}
Here is the javascript section i tried to alter, but i can't find anything after extensive searches on if this works...
function checkFile() {
if (document.s3Form.file.value=="") {
alert("Please, select a file.");
return false;
}
else if (document.s3Form.fType.value=="--None--") {
alert("Please, select a file type.");
return false;
}
else {
alert("Uploading...Please click OK and wait for page to refresh.");
document.s3Form.submit({
success: function(){
alert("Testing!");
insertFile();
},
});
}
}
Right now, the code below upon submit, first inserts a file THEN submits the form. This is problematic - I need for it to verify the form was successfully posted to Amazon S3 then insert the (token) file so it can link to it.
I basically need to reverse SubmitFile and InsertFile, but I'm not sure how to have (If form successfully sent, then run another javascript function). See very bottom for an attempt...Is this possible?
<apex:pageMessages id="pageErrors"></apex:pageMessages>
<form name="s3Form" action="https://s3.amazonaws./mybucket" method="post" enctype="multipart/form-data">
<input type="hidden" name="key"/>
<input type="hidden" name="AWSAccessKeyId" value="{!key}"/>
<input type="hidden" name="policy" value="{!policy}"/>
<input type="hidden" name="signature" value="{!signedPolicy}"/>
<input type="hidden" name="acl" value="private"/>
<input type="hidden" name="x-amz-meta-FileId" value="{!File__c.id}"/>
<input type="hidden" name="x-amz-meta-OrderId" value="{!OrderId}"/>
<input type="hidden" name="x-amz-meta-CustomerId" value="{!CustomerId}"/>
<input type="hidden" name="success_action_redirect" value="{!serverUrl}{!OrderId}"/>
<apex:pageBlock title="New File Upload" mode="maindetail" tabStyle="File__c"> <!-- rendered="{!open}"-->
<apex:pageBlockSection title="File Information" columns="2" collapsible="false" showHeader="false">
<apex:pageBlockSectionItem >
<apex:outputLabel value="Select File" for="selectFile"/>
<input id="selectedFile" type="file" size="25" name="file" onChange="setFileName(this.value)"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<apex:pageBlockButtons location="bottom">
<input class="btn" type="button" value="Upload File" onClick="checkFile();return false;"/>
<input class="btn" type="button" value="Cancel" onClick="cancelFile();return false;"/>
<input class="btn" type="button" value="Complete Order" onClick="pleteFile();return false;"/>
</apex:pageBlockButtons>
</apex:pageBlock>
<apex:outputText styleClass="footer" value="Please click Complete Order when all the required files are uploaded. Thank you." />
</form>
<apex:form id="sfForm"><!-- rendered="{!open}"-->
<apex:inputHidden id="hiddenServerURL" value="{!serverURL}"/>
<apex:inputHidden id="fileName" value="{!fileName}"/>
<apex:inputHidden id="contentType" value="{!contentType}"/>
<apex:inputHidden id="fileType" value="{!fileType}"/>
<apex:actionFunction name="insertFile" action="{!insertFile}" onplete="submitFile();return false;"/>
<apex:actionFunction name="pleteOrder" action="{!pleteOrder}"/>
<script type="text/javascript">
var sendFile = false;
document.getElementById('{!$Component.hiddenServerURL}').value = '{!$Api.Enterprise_Server_URL_140}';
function setFileName(file) {
var f = file.replace(/\\/g, "");
f = f.replace(/C\:fakepath/g, ""); <!--Required for IE8-->
document.s3Form.key.value = "{!CustomerName}/{!OrderName}/" + f;
document.getElementById('{!$Component.fileName}').value = f;
suffix = f.lastIndexOf(".") + 1;
contentType = f.slice(suffix);
document.getElementById('{!$Component.contentType}').value = contentType;
}
function setFileType(type) {
document.getElementById('{!$Component.fileType}').value = type;
}
function checkFile() {
if (document.s3Form.file.value=="") {
alert("Please, select a file.");
return false;
}
else if (document.s3Form.fType.value=="--None--") {
alert("Please, select a file type.");
return false;
}
else {
alert("Uploading...Please click OK and wait for page to refresh.");
insertFile();
sendFile = true;
}
}
function submitFile() {
if(sendFile = false) {
return false;
}
else {
document.s3Form.submit();
}
}
function pleteFile() {
pleteOrder();
}
</script>
</apex:form>
In the controller (extension):
//SF File insert on an object (passed from page)
public PageReference insertFile() {
this.file.Name = fileName;
this.file.Type__c = fileType;
this.file.Content__c = contentType;
insert this.file;
return null;
}
Here is the javascript section i tried to alter, but i can't find anything after extensive searches on if this works...
function checkFile() {
if (document.s3Form.file.value=="") {
alert("Please, select a file.");
return false;
}
else if (document.s3Form.fType.value=="--None--") {
alert("Please, select a file type.");
return false;
}
else {
alert("Uploading...Please click OK and wait for page to refresh.");
document.s3Form.submit({
success: function(){
alert("Testing!");
insertFile();
},
});
}
}
Share
Improve this question
asked Aug 17, 2011 at 21:08
tsalbtsalb
1772 gold badges4 silver badges10 bronze badges
2 Answers
Reset to default 1So if I'm understanding you correctly you want to:
- Validate file
- Upload file to amazon s3
- Save file token to salesforce
Not to throw a wrench in your plans but you might try pleting the whole routine in apex. Here's some pseudo code. Salesforce also has developed a toolkit for working with Amazon S3 so you shouldn't have to develop everything from scratch.
Visualforce Page:
<apex:page controller="MyController">
<apex:form>
<apex:inputFile value="{!file.body}" filename="{!file.name}"/>
<apex:mandButton value="Submit" action="{!submitFile}"/>
</apex:form>
</apex:page>
Apex Controller:
public class MyController {
public Document file { get; set; } { file = new Document(); } // dummy object for storing binary file data
public void submitFile() {
if(!validateFile())
return;
String s3Token = submitToS3();
if(s3Token != null) {
File__c newFile = new File__c(name = file.name, s3_token__c = s3Token);
insert newFile;
}
}
}
+1 on doing the work in Apex as opposed to Javascript.
But to continue with a potentially successful hack, try using apex:actionPoller for your form submit. When it wakes up it checks for success on your file insert. If after a few polls you still don't have success then flag a timeout.
Javascript novelties in Visualforce can be perilous, unless time is not a factor for you. Best exhaust Visualforce/Apex options first and only then venture into custom JavaScript in special cases or for lightweight UI tweaks, imo.