Post ‘multipart/form-data’ out of Salesforce.com with APEX

¿Es cierto que Salesforce no permite realizar peticiones HTTP (callouts) con datos multipart/form-data desde APEX? Pues la respuesta es que Salesforce sí lo permite, lo único que tenemos que tener en cuenta es qué tipo de datos admite el servidor destino al que enviamos la petición.

Esto es muy importante cuando queremos subir archivos desde Salesforce (vía APEX, por supuesto) a un servidor externo a Salesforce, como Box o WatchDox, por ejemplo. Esto resulta económicamente rentable, cuando el coste de almacenamiento del servidor externo es inferior al coste de almacenaniento de Salesforce.

Lo primero que debemos averiguar es qué tipo de datos admite el servidor externo en las peticiones con datos multipart/form-data. Puede ser que el servidor externo sólo admita contenido binario, o puede ser que admita contenido codificado en base64, o ambos.

En el primero de los casos, en el que el servidor destino sólo admita contenido binario, Enrico Murro, miembro de Cloudspokes al igual que yo, ha desarrollado hace escasos días una magnífica solución, que puedes ver aquí. Se trata de una solución que muchos desarrolladores de Salesforce estaban esperando, y que gracias a este reto de Cloudspokes en el que ambos hemos participado, pudimos investigar a fondo sobre este tema.

Si el servidor destino admite también contenido codificado en base64, en este caso la solución es mucho más sencilla. Esta fue la opción que yo opté para este reto, ya que el servidor destino admitía ambos tipos de contenido.

A continuación muestro un código de ejemplo para este tipo de servidores:

[sourcecode language=”javascript”] public static HTTPResponse uploadFile(String fileName, Blob fileBody, String contentType){

// Body
String boundary = String.valueOf(DateTime.now().getTime());
String body = ‘————‘ + boundary + ‘rn’;
body+=’Content-Disposition: form-data; name="data"; filename="’ + fileName + ‘"rn’;
body+=’Content-Transfer-Encoding: base64rn’;
if ((contentType == null) || (contentType == ”)){contentType = ‘application/octet-stream’;}
body+=’Content-Type: ‘ + contentType + ‘rnrn’;
body+=EncodingUtil.base64Encode(fileBody);
body+=’rn————‘ + boundary + ‘–‘;

// Instantiate a new HTTP request, specify the method (POST) as well as the endpoint
HttpRequest req = new HttpRequest();

// Set headers
req.setHeader(‘Content-Type’, ‘multipart/form-data; boundary=———-‘ + boundary);
req.setHeader(‘Content-Length’,String.valueof(body.length()));

// Set body
req.setBody(body);

// Set method and endpoint
req.setMethod(‘POST’);
req.setEndpoint(‘http://www.TuServidorExterno.com’);

// Send HTTP request and get HTTP response
Http http = new Http();
return(http.send(req));
}
[/sourcecode]

Puedes ver el vídeo de esta funcionalidad en acción correspondiente a mi solución creada para el reto de Cloudspokes, la cual permite subir todo tipo de archivos de hasta 3Mb a WatchDox desde Salesforce. Si el explorador web soporta HTML5, se pueden seleccionar varios archivos para subirlos en el mismo proceso, soporta drag&drop, y además se muestra una barra de progreso por cada archivo que se quiere subir.

Espero que este post os sirva de ayuda.

10 Comentarios. Dejar nuevo

Hi, thanks for the nice post. i m having problem with calling REST API; i hope you can help out. i’m getting error: 400 (SalesforceProxy-Endpoint not defined in header.) … Thanks in advance.
here is my code:

// Get a reference to jQuery that we can work with
$j = jQuery.noConflict();
// Get an instance of the REST API client and set the session ID
var client = new forcetk.Client();
client.setSessionToken(‘{!$Api.Session_ID}’);
$j.ajax({
url: “https://csX.salesforce.com/services/proxy/apexrest/Contact/v27.0/doGet/”,
type: ‘GET’,
dataType: ‘json’,
error: function(data1) { alert(‘error’); alert(data1.errorCode); },
beforeSend: function (xhr) {
xhr.setRequestHeader(‘Authorization’, “OAuth ” + client);
xhr.setRequestHeader(‘Accept’, “application/json”);
},
success: function() { alert(‘hello!’); }
});

Responder

I have created REST API:
@HttpGet
global static List getContact() {
List widgets = [SELECT Id, Name, Phone, sbscbr_num__c FROM Contact
];
return widgets;
}
I am trying to call this api through VF Page using JQuery ajax. I am able to call this API using workbench and getting JSON result also. But just not working through VF Page.
Hope i’m clear this time. Pls let me know if you have more questions. Thanks.

Responder

I agree but we are performing some test; moving forward we are planning to use REST API from different org also.

Responder

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Fill out this field
Fill out this field
Por favor, introduce una dirección de correo electrónico válida.
Necesita estar de acuerdo con los términos para continuar

¿Quieres que hablemos y plantearnos tus necesidades?
Menú