Uploading Images to Drupal 7 with Services (REST API) and Appcelerator

Uploading Images to Drupal 7 with Services (REST API) and Appcelerator

I’ll share more of this projects code later, but after a long and hard day of searching (and putting together ideas and code from MANY different sources) I thought I’d quickly share how to upload an image (or any file) to Drupal using the Services module and Appcelerator.

First, upload your file. You CANNOT upload a file AND create a node at the same time. There is an attach_file command that goes with node creation, but I haven’t been able to get it to work. I kept getting ’empty’ files over and over again, so here is the correct way to upload files using JSON:

var url = REST_PATH + 'file';
        var buffer = Ti.Utils.base64encode(image).toString();
      var file = {
           file: buffer,
           filename: data2.user.uid+'-'+new Date().getTime()+'.jpg'
       };
    // Create a connection
    var xhr3 = Titanium.Network.createHTTPClient();
    // Open the connection using POST
    xhr3.open("POST",url);

    xhr3.setRequestHeader('Content-Type','application/json');
    xhr3.setRequestHeader('X-CSRF-Token',Titanium.App.Properties.getString("userToken"));

    // Send the connection and the file object as argument
    xhr3.send(JSON.stringify(file));

    // When the connection loads we do:
    xhr3.onload = function() {

        var statusCode = xhr3.status;

        // Check if we have a valid status
        if(statusCode == 200) {
            console.log('filesent');

}

REST_PATH is the path to your Drupal REST server. You add ‘file’ to the URL to let Drupal know you’ll be working with a file…

var buffer = Ti.Utils.base64encode(image).toString();

My ‘buffer’ variable is where I had the most trouble. Drupal needs your file to be in a base 64 encoded string format. I somehow stumbled across Titaniums base64encode function after trying countless other options. ‘image’ is a blob of the image you want to upload (in my case I get this by snapping a photo with the camera and setting image equal to event.media (gives you a file blob). If you don’t add the .toString(), the encoding doesn’t work (if image WAS already a string, this wouldn’t be needed). Create a file object with the actual encoded file string and your filename (here I used the user ID, then a timestamp.

The HTTPClient stuff is pretty straight forward…

xhr3.setRequestHeader('X-CSRF-Token',Titanium.App.Properties.getString("userToken"));

This is another important piece. You’ll want to save your user Token from the JSON response from a the user log in. This MUST be sent in the HTTP header, otherwise you’ll get an access denied response (unless you allow anonymous users to have file uploading capabilities, but why would you want to do that?).

xhr3.send(JSON.stringify(file));

Make sure you stringify your file object before you send it, otherwise it will fail.

Basically how I created a node with an image attachment was:

  • Send Drupal the Username and Password to log into the site
  • Capture the response and saved the user token
  • Ran this section of code to upload the file
  • Captured THIS response to get the fid (you need this to attach it to a node)
  • Sent a node object
var node = {

node:{

title: data, type:'article',
body: {
und: [
{ value: data, format: 'full_html'}
]
},
field_image: {
und: [
{ fid: data4.fid}
]
},
uid: user.uid,
}
};

data4 is the variable holding the response from the file upload (don’t ask… I name things weird when I’m sick of trying to make things work).

The code to do all this is very simple, it was just getting through the scattered and dated documentation to make it all come together.

After I clean this up, I’ll share the whole process, but this was by far the least documented, so I wanted to share it now in case anyone else was using Drupal and Appcelerator Titanium. As always, leave us comments if you have questions.

Leave a Reply