I have a VF page that is used to load files to AWS. In the past the files were smaller and the 5M VF limit was fine. Now most of the files are larger than 5M and I can no longer upload them using this VF page.
What is the workaround or alternative?
I have a VF page that is used to load files to AWS. In the past the files were smaller and the 5M VF limit was fine. Now most of the files are larger than 5M and I can no longer upload them using this VF page.
What is the workaround or alternative?
Use the ajax toolkit to perform the upload from javascript. This way you avoid apex heap size limit. I've done it and successfully uploaded files up to ~35 mb in size.
1) Reference the ajax toolkit in your visualforce page.
<apex:includeScript value="../../soap/ajax/26.0/connection.js" />
2) Write javascript to upload to server (in this case its as an attachment, but contents or documents should also work).
function uploadAttachment(filecontent, filename, filetype, parentId) {
var attachment = new sforce.SObject('Attachment');
attachment.Name = filename;
attachment.IsPrivate = false;
attachment.ContentType = filetype;
attachment.Body = filecontent;
attachment.Description = filename;
attachment.ParentId = parentId;
sforce.connection.create([attachment]);
}
3) Write some js to get at file content. This is the only difficult step. You could use HTML5 file API but its support is limited. Ill do a drag-n-drop example as its more supported.
<script>
var dropzone = document.getElementById('dropzone');
dropzone.addEventListener("drop", drop, false);
function drop(evt) {
endEvent(evt);
var files = evt.originalEvent.dataTransfer.files;
if (files.length > 0) {
try {
uploadFiles(files);
} catch(error) {
alert('An error occured in sfdc-dragndrop.js: ' + error);
}
}
}
function uploadFiles(files) {
for(var index = 0, file; file = files[index]; index++) {
var reader = new FileReader();
reader.onloadend =
(function(file) {
return function(evt) {
var fileContent = getFileContent(evt.target.result)
var parentId = <id of attachment parent>;
uploadAttachment(fileContent, file.name, file.type, parentId);
};
})(file);
reader.readAsDataURL(file);
}
}
function getFileContent(fileData) {
var fileContent = String(fileData);
return fileContent.substr(fileContent.indexOf(',') + 1);
}
</script>
Hopefully all that code works and gets you what you need (i dug it out of an old project and changed it a little on the fly to be stackexchange-friendly), if not it should be a step in the right direction.
Based the example above but using HTML5 and the Content Objects:
<apex:page >
<script type="text/javascript">__sfdcSessionId = '{!$Api.Session_Id}';</script>
<script src="../../soap/ajax/30.0/connection.js" type="text/javascript"></script>
<script language="JavaScript">
function uploadContentVersion(filename, filecontent) {
var contentVersion = new sforce.SObject('ContentVersion');
contentVersion.pathOnClient = filename;
// Set origin to 'C' if uploading to content
// and set the FirstPublishLocationId to either a UserId or ContentWorkspaceId
contentVersion.origin = 'H';
contentVersion.VersionData = filecontent;
var results = sforce.connection.create([contentVersion]);
for (var i = 0; i < results.length; i++) {
if (results[i].getBoolean("success")) {
alert('New ContentVersion record created:' + results[i].id);
}
else {
alert('Failed:' + results[i]);
}
}
}
function fileSelected() {
var file = document.getElementById('fileToUpload').files[0];
if (file) {
var fileSize = 0;
if (file.size > (36 * 1024 * 1024)) {
alert('File too large, greater than 36MB');
return;
}
if (file.size > 1024 * 1024)
fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
else
fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
}
}
function uploadFile() {
var file = document.getElementById('fileToUpload').files[0];
var reader = new FileReader();
reader.onload = loaded;
reader.onerror = errorHandler;
reader.readAsDataURL(file);
}
function loaded(evt) {
var filename = document.getElementById('fileToUpload').files[0].name;
var fileContent = String(evt.target.result);
fileContent = fileContent.substr(fileContent.indexOf(',') + 1);
uploadContentVersion(filename, fileContent);
}
function errorHandler(evt) {
if (evt.target.error.name == 'NotReadableError') {
alert('File could not be read');
}
else {
alert(evt.target.error);
}
}
</script>
<title>Upload Files using XMLHttpRequest - Minimal</title>
<form id="form1" enctype="multipart/form-data" method="post">
<div class="row">
<label for="fileToUpload">Select a File to Upload</label><br />
<input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/>
</div>
<div id="fileName"></div>
<div id="fileSize"></div>
<div id="fileType"></div>
<div class="row">
<input type="button" onclick="uploadFile()" value="Upload" />
</div>
</form>
</apex:page>