If you are building a client application and trying to upload a file to Salesforce using one a custom REST service, chances are you will encounter the error described in our previous article - Apex REST does not support multipart/form-data requests[SOLVED] - which discusses how
multipart/form-data request handling works and the hack to build one in Salesforce. In this article we will discuss the possible options to design a REST service that can accept
multipart/form-data request with files and upload to Salesforce.
If the client side application is setup by you yourself and you have complete control over the calling code, this hack follows our previous article and suggests to remove the content-type header and additionally pass the generated boundary as a URL parameter (to avoid discovering the boundary from the body in our apex code)
If you have a middleware/API management tool viz. apigee and at max you can only remove the content-type header, you end up with 2 options:
- Read the incoming blob
- Save it in a String (boom you might hit error if the attachment is so large that the
EncodingUtil.base64Decode(bodyString)crosses the max string length). This applies to Option 1 as well
- If you don't hit any limit in step#2 then go ahead and insert the content version - and optionally contentdocumentlink
- Read the incoming blob - don't save it in a String (escape the max string length error) - also do not insert the content version directly.
- Call the standard content version api (and optionally contentdocumentlink api) - (but boom you might hit another limit error i.e.,
System.CalloutException: Exceeded max size limit of 6000000- yes the blob size counts against the
HttpRequestsize that has a limit of 6MB for synchronous and 12 MB for asynchronous).
Therefore to upload large size Files from a client application to Salesforce it is recommended to use and call the standard ContentVersion and optionally ContentDocumentLink API directly. Please let me know here if you are looking for an article on this.
Below are the code blocks for each of the options that we discussed above: