Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
JavaScript snippet for uploading fille to Salesforce as ContentVersion and sharing to record as ContentDocumentLink via jsforce and jquery.
<apex:page>
<head>
<script src="{!$Resource.jquery224}"></script> <!-- https://jquery.com/ -->
<script src="{!$Resource.jsforce170}"></script> <!-- https://jsforce.github.io/ -->
<script>$j = jQuery.noConflict();</script>
</head>
<body>
<form>
<input type="file" id="fileInput"/>
</form>
</body>
<script>
var conn = new jsforce.Connection({ accessToken: '{!$Api.Session_Id}' });
/**
* Uses Chatter REST API to upload files up to 2GB.
*/
function uploadFile() {
// ... show waiting indicator
var fileInput = $j('#fileInput');
if ( $j.trim( fileInput.val() ).length == 0 ) {
// ... hide waiting indicator
return;
}
// https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
var file = fileInput[0].files[0];
var fileName = getFileNameWithExtension( file );
var reader = new FileReader();
reader.addEventListener('load', function() {
saveFile( fileName, reader.result, '{!record.id}' );
});
reader.readAsDataURL( file );
}
/**
* Saves the file asynchronously to Salesforce and shares it to the record.
*
* @param fileName
* Name of the file, for best results should include extension (e.g. 'file.txt')
* @param base64
* Base64 encoded file data
* @param recordId
* The Salesforce record to share the file to
*
* Returns a promise per the jsforce library.
*/
function saveFile( fileName, base64, recordId ) {
var path = '/services/data/v40.0';
return conn.requestPost( path + '/composite/', {
'allOrNone' : true,
'compositeRequest' : [
{
'method' : 'POST',
'url' : path + '/sobjects/ContentVersion',
'referenceId' : 'newFile',
'body' : {
'Title' : fileName,
'PathOnClient' : fileName,
'VersionData' : base64,
'FirstPublishLocationId' : recordId
}
}
]
})
.then( validateCompositeResponse )
.then( function( response ) {
// get new file id
var contentVersionId = null;
for ( var i = 0; i < response.compositeResponse.length; i++ ) {
if ( response.compositeResponse[i].referenceId === 'newFile' ) {
contentVersionId = response.compositeResponse[i].body.id;
break;
}
}
// ... do something with the new file id
}).catch( function( err ) {
console.error( err );
// ... show error to user
}).then( function() {
// this last 'then' after the 'catch' acts like a finally block of try..catch..finally
// https://stackoverflow.com/questions/35999072/what-is-the-equivalent-of-bluebird-promise-finally-in-native-es6-promises
// ... hide waiting indicator
});
}
/**
* Gets the name with extension of a file input reference, like 'file.txt'.
* Replaces any other periods (.) with underscores (_) otherwise Salesforce
* ignores all text in the filename after the first dot.
*
* @param file
* js reference of a file retrieved from an html input element
* e.g. fileInput.files[0]
*/
function getFileNameWithExtension( file ) {
var extIndex = file.name.lastIndexOf( '.' );
var extension = file.name.substring( extIndex );
var fileName = file.name.substring( 0, extIndex );
fileName = fileName.replace( /\./g, '_' );
fileName += extension;
return fileName;
}
/**
* Checks each sub-response for an error code
* and throws error if finds one, else does nothing.
*/
function validateCompositeResponse( response ) {
return new Promise( function( resolve, reject ) {
console.log('validating composite response');
for ( var i = 0; i < response.compositeResponse.length; i++ ) {
var body = response.compositeResponse[i].body[0];
// ignore the 'processing halted' messages as that just indicates
// that sub-request wasn't the one that blew up, keep looking
if ( body && body.errorCode && body.errorCode != 'PROCESSING_HALTED' ) {
reject( body.message );
}
}
resolve( response );
});
}
</script>
</apex:page>
@spacemishka

This comment has been minimized.

Copy link

commented Aug 28, 2017

Hello,

i have problem with your script. During the upload of an image, there are few bytes added to the file and so the file gets corrupt.

Can you give me an advise?

thanks
Peter

@chunwu

This comment has been minimized.

Copy link

commented Nov 26, 2018

Hello,

i have problem with your script. During the upload of an image, there are few bytes added to the file and so the file gets corrupt.

Can you give me an advise?

thanks
Peter

The documentation says:

Note: The file's result results in a string that cannot be directly decoded as Base64. To retrieve only the Base64 encoded string, you must remove data:/;base64, from the string.

So you need to strip that prefix:

var data = reader.result.split(',')[1];
saveFile( fileName, data, '{!record.id}' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.