function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
foundation_devfoundation_dev 

http callout with multipart/form-data

Hi,

I am trying to make HTTP POST request with multipart/form-data, the problem is that the request is sent but without the body part. I was trying the solution: http://enreeco.blogspot.it/2013/01/salesforce-apex-post-mutipartform-data.html, but it doesn't worked for me. I think it is the same problem as: http://boards.developerforce.com/t5/Apex-Code-Development/Image-upload-using-multipart-form-data/m-p/243335/highlight/true#M42610. Will this issue be solved? Is there any alternative to HttpRequest?

Mohith Kumar ShrivastavaMohith Kumar Shrivastava
private void uploadFile(String folderId,Attachment file,String token){
  String boundary = '----------------------------741e90d31eff';
  String header = '--'+boundary+'\nContent-Disposition: form-data; name="file"; filename="'+file.name+'";\nContent-Type: application/octet-stream';
  // GW: Do not prepend footer with \r\n, you'll see why in a moment
  // String footer = '\r\n--'+boundary+'--'; 
  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(file.body);
  // GW: Do not encode footer yet
  // String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));

  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('==')) {
    // 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 \n\n instead of \r\n replace == with 'oK'
    last4Bytes = last4Bytes.substring(0,2) + '0K';
    bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
    // We have appended the \r\n to the Blob, so leave footer as it is.
    String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
  } else if(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
    footer = '\n' + footer;
    String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);              
  } else {
    // Prepend the CR LF to the footer
    footer = '\r\n' + footer;
    String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);  
  }

  String sUrl = 'https://upload.box.com/api/2.0/files/content?parent_id='+folderId;
  HttpRequest req = new HttpRequest();
  req.setHeader('Content-Type','multipart/form-data; boundary='+boundary);
  req.setMethod('POST');
  req.setEndpoint(sUrl);
  req.setBodyAsBlob(bodyBlob);
  req.setTimeout(60000);
  req.setHeader('Authorization', 'Bearer '+token);
  req.setHeader('Content-Length',String.valueof(req.getBodyAsBlob().size()));
  Http http = new Http();
  HTTPResponse res = http.send(req);
}
Try this code that shows how to use multipart/form-data in the http.All thanks to the blog you mentioned in the question.
Jeyavel SwaminathanJeyavel Swaminathan
Here's my solution which works..and in this case i send a field (xml content) and file (pdf) as part of the payload. and i believe you should be able to switch contents to other types.
 
string   formBoundary = '----sfdc-multi-form',
         footer = '\r\n--'+formBoundary+'--',                
         headerForm = '--'+formBoundary+'\r\nContent-Disposition: form-data; name="{0}";\r\n\n',
         headerFile = '--'+formBoundary+'\r\nContent-Disposition: form-data; name="{0}"; filename="{1}";\r\nContent-Type: {2}\r\n\n';

string documentHexContent = EncodingUtil.convertToHex(blob.valueOf((string.format(headerForm, new list<String> {'document'})+
                                                                            <XML content>)));
string fileHexContent = EncodingUtil.convertToHex(blob.valueOf('\r\n'+string.format(headerFile, new list<String> {'filename',fileName,'application/pdf'})))+
                                    EncodingUtil.convertToHex(<PDF file>)+
                                    EncodingUtil.convertToHex(blob.valueof(footer));
HttpRequest req = new HttpRequest();            
            req.setMethod('POST');
            req.setEndpoint('<resource URL>');
            req.setHeader('Accept', '<Accept content type>');
            req.setHeader('Content-Type', 'multipart/form-data; boundary='+formBoundary);            
            req.setBodyAsBlob(body);
            req.setHeader('Content-Length',string.valueOf(req.getBodyAsBlob().size()));
HttpResponse resp = new Http().send(req);
sivasankar.ksivasankar.k
@Swaminathan, We are trying to upload the Image file, but it was not worked, the request sent without the body. Have you tried the above solution for image file? 
Please advise if you have any solution.

Thanks,
 
Deepak GerianiDeepak Geriani

Hello foundation_dev

what you are looking for is not supported by the salesforce apex callout. it's still in the salesforce Idea Exchange here is the link for the same.
https://trailblazer.salesforce.com/ideaView?id=08730000000Kr80AAC
You can vote for it but currently, multipart/form-data header is not supported.

please mark as solved if your issue is resolved