Post multipart without Base64 Encoding the body

I am trying to POST a PDF attachment to a Restful web service (not under my control). My issue is that I need to get put the raw bytes of the PDF into the Body of the request and whenever I call Blob.toString(), I get stopped by a UTF-8 String error:

BLOB is not a valid UTF-8 String

I’ve tried to put the base64 encoded bytes into the body instead, but the web service doesn’t seem to support it.

public Dom.Document uploadFile(Attachment attachment){
    // Body
    String boundary = '------------' + String.valueOf(DateTime.now().getTime());
    string body = '';
    body+= boundary;
    body+= '\r\n';
    body+= 'Content-Disposition: form-data; name=\"file\";';
    body+= 'filename=\"' + attachment.name + '\"';
    body+= '\r\n';
    //body+= 'Content-Transfer-Encoding: base64\r\n';
    body+= 'Content-Type: application/octet-stream';
    body+= '\r\n\r\n';
    body+= attachment.body.toString();
    body+= '\r\n' + boundary + '\r\n';

    HttpRequest req = new HttpRequest();

    req.setEndpoint('http://connect.sandbox.mimeo.com/2012/02/storageservice/test');

    // Set headers
    req.setHeader('Authorization', authorizationData);
    req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
    req.setHeader('Content-Length',String.valueof(body.length()));
    req.setMethod('POST');
    req.setTimeOut(120000);

    req.setBody(body);

    Http http = new Http();

    HttpResponse res = http.send(req);
    Dom.Document retDocument = res.getBodyDocument();
    return retDocument;
}

Is there anyway to get the blob as a non utf8 string? I thinking about trying to write my own base64 decode that returns a string but I don’t even know if this is even possible in apex.

Update

Just to give some more info here is the request I’m trying to replicate in Apex. This was made using Mimeo’s C# library and was successful. Mimeo provides no documentation for this service that I can find:

POST http://connect.sandbox.mimeo.com/2012/02/storageservice/test HTTP/1.1
Authorization: Basic [removed]
Content-Type: multipart/form-data; boundary=----------8d0de7b15063540
Host: connect.sandbox.mimeo.com
Content-Length: 493827
Expect: 100-continue
Connection: Keep-Alive

------------8d0de7b15063540
Content-Disposition: form-data; name="file"; filename="printme.pdf"
Content-Type: application/octet-stream

[BINARY PDF]

------------8d0de7b15063540

Answer

This is how I send attachments. All credits(& explanation) http://enreeco.blogspot.in/2013/01/salesforce-apex-post-mutipartform-data.html

@Future(callout=true)
public static void uploadFile(Blob file_body, String file_name, String reqEndPoint){

          String boundary = '----------------------------741e90d31eff';
          String header = '--'+boundary+'\r\nContent-Disposition: form-data; name="file"; filename="'+file_name+'"\r\nContent-Type: application/octet-stream'; // added '\r's removed ';' see Tim Smith's comment
          String footer = '\r\n--'+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);
          String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));

          Blob bodyBlob = null;
          String last4Bytes = bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
          if(last4Bytes.endsWith('='))
          {
               Blob decoded4Bytes = EncodingUtil.base64Decode(last4Bytes);
               HttpRequest tmp = new HttpRequest();
               tmp.setBodyAsBlob(decoded4Bytes);
               String last4BytesFooter = tmp.getBody()+footer;   
               bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded.substring(0,bodyEncoded.length()-4)+EncodingUtil.base64Encode(Blob.valueOf(last4BytesFooter)));
          }
          else
          {
                bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
          }

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

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


}

Attribution
Source : Link , Question Author : NSjonas , Answer Author : shmuel friedman

Leave a Comment