[SalesForce] Multipart form data post file with multiple form parameters

I am gone through this post and wanted to add one more form data parameter, but when I am sending a request that parameter it not getting posted into form data, please advise what I am missing.

Here is my code.

Attachment objPDF = [SELECT ID, Name, Body FROM Attachment where id = '00P0I00000u85YXUAY'
    LIMIT 1
];
String strTargetURL = 'https://www.perfectaudit.com/api/v1/book/upload';

String boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW';
string header1 = '--' + boundary + '\nContent-Disposition: form-data; name="pk"';
String header1Encoded = EncodingUtil.base64Encode(Blob.valueOf(header1 + '\r\n\r\n'));
while (header1Encoded.endsWith('=')) {
    header1 += ' ';
    header1Encoded = EncodingUtil.base64Encode(Blob.valueOf(header1 + '\r\n\r\n'));
}
String body1Encoded = EncodingUtil.base64Encode(Blob.valueOf('68749\r\n'));
String last4Bytes = body1Encoded.substring(body1Encoded.length() - 4, body1Encoded.length());
if (last4Bytes.endsWith('==')) {
    last4Bytes = last4Bytes.substring(0, 2) + '0K';
    body1Encoded = body1Encoded.substring(0, body1Encoded.length() - 4) + last4Bytes;    
} else if (last4Bytes.endsWith('=')) {
    last4Bytes = last4Bytes.substring(0, 3) + 'N';
    body1Encoded = body1Encoded.substring(0, body1Encoded.length() - 4) + last4Bytes;    
}

String header = '--' + boundary + '\nContent-Disposition: form-data; name="upload"; filename="' + objPDF.Name + '";\nContent-Type: application/pdf';
String footer = '--' + boundary + '--';
String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header + '\r\n\r\n'));
while (headerEncoded.endsWith('=')) {
    header += ' ';
    headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header + '\r\n\r\n'));
}
String bodyEncoded = EncodingUtil.base64Encode(Blob.valueOf('This is text file'));
Blob bodyBlob = null;
last4Bytes = bodyEncoded.substring(bodyEncoded.length() - 4, bodyEncoded.length());
if (last4Bytes.endsWith('==')) {
    last4Bytes = last4Bytes.substring(0, 2) + '0K';
    bodyEncoded = bodyEncoded.substring(0, bodyEncoded.length() - 4) + last4Bytes;
    String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    bodyBlob = EncodingUtil.base64Decode(header1Encoded + body1Encoded + headerEncoded + bodyEncoded + footerEncoded);    
} else if (last4Bytes.endsWith('=')) {
    last4Bytes = last4Bytes.substring(0, 3) + 'N';
    bodyEncoded = bodyEncoded.substring(0, bodyEncoded.length() - 4) + last4Bytes;
    footer = '\r\n' + footer;
    String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    bodyBlob = EncodingUtil.base64Decode(header1Encoded + body1Encoded + headerEncoded + bodyEncoded + footerEncoded);    
} else {
    footer = '\n' + footer;
    String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    bodyBlob = EncodingUtil.base64Decode(header1Encoded + body1Encoded + headerEncoded + bodyEncoded + footerEncoded);    
}

HttpRequest req = new HttpRequest();

String userName = 'xxxxx';
String password = 'xxxxx';
Blob headerValue = Blob.valueOf(userName + ':' + password);
String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);
req.setHeader('Authorization', authorizationHeader);

req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
req.setMethod('POST');
req.setEndpoint(strTargetURL);
req.setBodyAsBlob(bodyBlob);
req.setTimeout(120000);

Http http = new Http();
HTTPResponse res = http.send(req);
system.debug(res.getBody());

I want to do below request using apex.

POST /api/v1/book/upload HTTP/1.1
Host: www.perfectaudit.com
Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Cache-Control: no-cache
Postman-Token: 356b00b1-0d9e-5332-1c80-c5b08ba3e49a
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="pk"

68749
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="upload"; filename="ticketmsrtc_18112017.pdf"
Content-Type: application/pdf


------WebKitFormBoundary7MA4YWxkTrZu0gW--

I am able to post a file but "pk" parameter is missing from form data.

Payload:-

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="pk"  

68749

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="upload"; filename="eStmt_2017-11-30 (1).pdf";
Content-Type: application/pdf  

***PDF DATA***
------WebKitFormBoundary7MA4YWxkTrZu0gW--

Best Answer

I'd avoid manually handling the Base64 encoding yourself and the application of Grant Wickman's solution to avoid padding characters on the binary data before the multipart boundary.

I looked at this in some detail in relation to sending multipart/formdata messages to the Einstein Vision Services.

Instead, use something like the HttpFormBuilder that MetaMind provided. It will provide a much more consistent application of the CR LF allocation between the part data/bytes and the multipart boundary.

Related Topic