Jigarius
Jigarius

Reputation: 416

Drupal Services - Direct file URL instead of file resource reference

I am using Drupal services and services_entity module to build a web service. The problem is that when a file is attached to an entity using fields, etc, the service endpoints display the file as resource reference as:

array (
    resource: file,
    id: xx,
    uri: /entity_file/xx.json
)

The thing is, every time you wish to display a file you will have to make 2 or more requests:

The question is, how to get the file URLs directly without having to make additional requests. So, the preferred response would be:

array (
    resource: file,
    id: xx,
    uri: /entity_file/xx.json,
    url: http://.../sites/.../files/foo/bar/b-reft.jpg
)

I looked for hours but did not find an answer, so I thought I would share the solution I found. I believe it would help many (and I also wish I could share my module for complex index query parameter support for services_entity module).

Upvotes: 0

Views: 226

Answers (1)

Jigarius
Jigarius

Reputation: 416

Declare a Resource Controller

Since the data is returned by a ServicesEntityResourceController, I decided to declare my own resource controller using hook_services_entity_resource_info().

/**
 * Implements hook_entity_resource_info()
 */
function c11n_services_entity_resource_info() {

    $output = array();

    $output['c11n'] = array (
        'title' => 'Clean Entity Processor - Customized',
        'description' => 'An entity wrapper based on the "Clean Entity Wrapper" wrapper with certain fixes and improvements.',
        'class' => 'ServicesEntityResourceControllerC11n',
    );

    return $output;

}

Declare Controller Class

After this, I declared the controller class:

ServicesEntityResourceControllerC11n extends ServicesEntityResourceControllerClean

Override the get_resource_reference() method

The final touch (toque final) would be to add the file URL. I decided to work on the output of the parent class and add in the URL for a file. Actual data is returned by the ServicesEntityResourceController::get_resource_reference() method. So, I overrode it like this and it was done.

protected function get_resource_reference($resource, $id) {

    $output = parent::get_resource_reference($resource, $id);

    switch ($resource):
        case 'file':
            $file = file_load($id);
            if ($file)
                $output['url'] = file_create_url($file->uri);
            break;
        case 'taxonomy_term':
            // Do something for taxonomy terms
            break;
    endswitch;

    return $output;

}

It solves the issue. However, I do not claim it to be the best solution, but having some solution is better than having none.

Alternative Solution

You can alter the entity_file resource and add a targeted_action named download or embed. In the callback, simply send out the headers for the file mime-type and then render the file contents using fpasthru() or echo file_get_contents().

Upvotes: 0

Related Questions