Last active
November 12, 2022 00:31
-
-
Save jonny-harte/4d49f6fbff40d7fdcdb9c6b5e8a20b57 to your computer and use it in GitHub Desktop.
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
public with sharing class HttpFormDataHandler { | |
public static Blob createRequestBody(String boundary, Object request) { | |
String last4Bytes = ''; | |
List<String> requestBody = new List<String>(); | |
Map<String, Object> requestMap = (Map<String, Object>) JSON.deserializeUntyped( | |
JSON.serialize(request) | |
); | |
for (String key : requestMap.keySet()) { | |
try { | |
if (requestMap.get(key) == null) { | |
continue; | |
} | |
for (Object value : (List<Object>) requestMap.get(key)) { | |
String entry = createBase64RequestBodyEntry( | |
last4Bytes, | |
boundary, | |
key, | |
value | |
); | |
last4Bytes = entry.substring(entry.length() - 4, entry.length()); | |
requestBody.add(entry.removeEnd(last4Bytes)); | |
} | |
} catch (TypeException e) { | |
String entry = createBase64RequestBodyEntry( | |
last4Bytes, | |
boundary, | |
key, | |
requestMap.get(key) | |
); | |
last4Bytes = entry.substring(entry.length() - 4, entry.length()); | |
requestBody.add(entry.removeEnd(last4Bytes)); | |
} | |
} | |
requestBody.add( | |
encodeBase64StringWithNewLine(last4Bytes, '--' + boundary + '--') | |
); | |
return EncodingUtil.base64Decode(String.join(requestBody, '')); | |
} | |
public static String createContentDisposition(String name, String value) { | |
String schemaName = ExternalServiceHelper.translateVariable(name); | |
return 'Content-Disposition: form-data; name="' + | |
schemaName + | |
'"\r\n\r\n' + | |
value; | |
} | |
public static String createContentDispositionFile( | |
String name, | |
ContentVersion file | |
) { | |
String contentType = MimeHelper.getMimeType(file.FileExtension); | |
String schemaName = ExternalServiceHelper.translateVariable(name); | |
return 'Content-Disposition: form-data; name="' + | |
schemaName + | |
'"; filename="' + | |
file.Title + | |
'.' + | |
file.FileExtension + | |
'"\r\nContent-Type: ' + | |
contentType; | |
} | |
public static Param createParam(String name, ContentVersion file) { | |
String contentDisposition = createContentDispositionFile(name, file); | |
String encodedVersionData = EncodingUtil.base64Encode(file.VersionData); | |
Param param = new Param(contentDisposition, encodedVersionData); | |
return param; | |
} | |
private static String createBase64RequestBodyEntry( | |
String last4Bytes, | |
String boundary, | |
String key, | |
Object value | |
) { | |
String entry = '--' + boundary + '\r\n'; | |
try { | |
Param param = (Param) JSON.deserialize( | |
JSON.serialize(value), | |
Param.class | |
); | |
entry += param.contentDisposition; | |
if (param.file != null) { | |
// TODO: Split into own function. | |
String encodedEntry = ''; | |
if (last4Bytes == '') { | |
encodedEntry = encodeBase64String(entry + '\r\n\r\n'); | |
} else { | |
encodedEntry = encodeBase64StringWithNewLine( | |
last4Bytes, | |
entry + '\r\n\r\n' | |
); | |
} | |
while (encodedEntry.endsWith('=')) { | |
entry += ' '; | |
if (last4Bytes == '') { | |
encodedEntry = encodeBase64String(entry + '\r\n\r\n'); | |
} else { | |
encodedEntry = encodeBase64StringWithNewLine( | |
last4Bytes, | |
entry + '\r\n\r\n' | |
); | |
} | |
} | |
return encodedEntry + param.file; | |
} | |
} catch (JSONException e) { | |
entry += createContentDisposition(key, (String) value); | |
} | |
if (last4Bytes == '') { | |
return encodeBase64String(entry); | |
} | |
return encodeBase64StringWithNewLine(last4Bytes, entry); | |
} | |
private static String encodeBase64String(String value) { | |
if (String.isBlank(value)) { | |
return value; | |
} | |
return EncodingUtil.base64Encode(Blob.valueOf(value)); | |
} | |
private static String encodeBase64String(Blob value) { | |
if (value == null) { | |
return ''; | |
} | |
return EncodingUtil.base64Encode(value); | |
} | |
private static String encodeBase64StringWithNewLine( | |
String encodedText, | |
String newText | |
) { | |
String paddingEnd = ''; | |
String paddingStart = ''; | |
String paddedText = ''; | |
String last4Bytes = encodedText.substring( | |
encodedText.length() - 4, | |
encodedText.length() | |
); | |
if (last4Bytes.endsWith('==')) { | |
paddingEnd = last4Bytes.substring(0, 2) + '0K'; | |
paddedText = | |
encodedText.substring(0, encodedText.length() - 4) + paddingEnd; | |
} else if (last4Bytes.endsWith('=')) { | |
paddingEnd = last4Bytes.substring(0, 3) + 'N'; | |
paddingStart = '\n'; | |
paddedText = | |
encodedText.substring(0, encodedText.length() - 4) + paddingEnd; | |
} else { | |
paddingStart = '\r\n'; | |
paddedText = encodedText; | |
} | |
return paddedText + encodeBase64String(paddingStart + newText); | |
} | |
public class Param { | |
private String contentDisposition; | |
private String file; | |
public Param(String contentDisposition, String file) { | |
this.contentDisposition = contentDisposition; | |
this.file = file; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment