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:

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));
    }

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.

Anuncios

10 comentarios en “Post ‘multipart/form-data’ out of Salesforce.com with APEX

  1. 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!’); }
    });

  2. 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

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s