With the assistance of an unnamed source and these links:
http://enreeco.blogspot.com/2013/01/salesforce-apex-post-mutipartform-data.html
How can I compose a multipart/form-data request?
, I was able to figure it out. Here is the code that returned back a positive response:
Public Static blob build_SBA_Blob(string fileName, string docID, string eTranSlug, blob contVers) {
//query for File
ContentVersion file = [SELECT Title, PathOnClient, VersionData FROM ContentVersion WHERE ContentDocumentId = '0693J0000007xV8QAI' AND IsLatest = true];
docID = '3';
eTranSlug = 'etran number';
fileName = file.PathOnClient;
contVers = file.VersionData;
//STEP X1: Create the header of the form-data
system.debug('STEP X1: Create the header of the form-data');
string strHeader;
strHeader = '--1ff13444ed8140c7a32fc4e6451aa76d\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n'+fileName;
strHeader += '\r\n--1ff13444ed8140c7a32fc4e6451aa76d\r\nContent-Disposition: form-data; name=\"document_type\"\r\n\r\n'+docID;
strHeader += '\r\n--1ff13444ed8140c7a32fc4e6451aa76d\r\nContent-Disposition: form-data; name=\"etran_loan\"\r\n\r\n'+eTranSlug;
strHeader += '\r\n--1ff13444ed8140c7a32fc4e6451aa76d\r\nContent-Disposition: form-data; name=\"document\"; filename=\"' + fileName + '\"\r\n\r\n';
system.debug(strHeader);
//STEP X2: Remove padding spaces from header
system.debug('STEP X2: Remove padding spaces from header');
String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(strHeader));
while(headerEncoded.endsWith('='))
{
strHeader+=' ';
headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(strHeader));
}
//STEP X3: Create the body and footer, handling the padding spaces
system.debug('STEP X3: Create the body and footer, handling the padding spaces');
string strFooter = '--1ff13444ed8140c7a32fc4e6451aa76d--';
String bodyEncoded = EncodingUtil.base64Encode(contVers);
Blob bodyBlob = null;
String last4Bytes = bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
// GW: replacement section to get rid of padding without corrupting data
if(last4Bytes.endsWith('==')) {
system.debug('last4Bytes.endsWith(\'==\')');
// The '==' sequence indicates that the last group contained only one 8 bit byte
// 8 digit binary representation of CR is 00001101
// 8 digit binary representation of LF is 00001010
// Stitch them together and then from the right split them into 6 bit chunks
// 0000110100001010 becomes 0000 110100 001010
// Note the first 4 bits 0000 are identical to the padding used to encode the
// second original 6 bit chunk, this is handy it means we can hard code the response in
// The decimal values of 110100 001010 are 52 10
// The base64 mapping values of 52 10 are 0 K
// See http://en.wikipedia.org/wiki/Base64 for base64 mapping table
// Therefore, we replace == with 0K
// Note: if using nn instead of rn replace == with 'oK'
last4Bytes = last4Bytes.substring(0,2) + '0K';
bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
// We have appended the rn to the Blob, so leave footer as it is.
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(strFooter));
//PUT IT ALL TOGETHER IN THE BLOB
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
} else if(last4Bytes.endsWith('=')) {
system.debug('last4Bytes.endsWith(\'=\')');
// '=' indicates that encoded data already contained two out of 3x 8 bit bytes
// We replace final 8 bit byte with a CR e.g. r
// 8 digit binary representation of CR is 00001101
// Ignore the first 2 bits of 00 001101 they have already been used up as padding
// for the existing data.
// The Decimal value of 001101 is 13
// The base64 value of 13 is N
// Therefore, we replace = with N
// Note: if using n instead of r replace = with 'K'
last4Bytes = last4Bytes.substring(0,3) + 'N';
bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
// We have appended the CR e.g. r, still need to prepend the line feed to the footer
strFooter = 'n' + strFooter;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(strFooter));
//PUT IT ALL TOGETHER IN THE BLOB
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
} else {
system.debug('else');
// Prepend the CR LF to the footer
strFooter = 'rn' + strFooter;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(strFooter));
//PUT IT ALL TOGETHER IN THE BLOB
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
}
ETranDetails__c etranDetails = ETranDetails__c.getOrgDefaults();
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type','multipart/form-data; charset="UTF-8"; boundary="1ff13444ed8140c7a32fc4e6451aa76d"');
req.setHeader('Authorization', etranDetails.API_Key__c);
req.setHeader('Vendor-Key', etranDetails.Vendor_Key__c);
req.setMethod('POST');
req.setEndpoint(etranDetails.Forgiveness_Endpoint_For_Upload_Docs__c);
req.setBodyAsBlob(bodyBlob);
req.setTimeout(120000);
Http http = new Http();
HTTPResponse res = http.send(req);
system.debug('what came back?'+res.getStatusCode()+' '+res.getBody());
return bodyBlob;
}