JavaScript snippet for uploading fille to Salesforce as ContentVersion and sharing to record as ContentDocumentLink via jsforce and jquery.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
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
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