1

This is an unusual one. Let's say I have two web servers A and B. How would I go about making a link to a file from a Drupal website on server A to a file on server B such that the link is secure (the link to the file can't be accessed directly/shared)? I would have some control over server B, but it would just be a standard web server.

The reason for wanting this is that I need to serve some files to users behind the "Great Firewall of China", but the website is within China.

1

The first thing that pops to mind is to create a custom module, with a menu callback to obfuscate the real url. This is the same way the drupal private filesystem (private://) handles this.

  • Create a menu entry in your custom module's hook_menu() to obfuscate the real url and perform access checks.

    function my_module_menu() {
      $items['my-module/download'] = array(
        'title' => 'File download',
        'page callback' => 'my_module_page_callback',
        'access callback' => TRUE, // Let the page callback handle the checks.
        'type' => MENU_CALLBACK,
      );
    }
    
  • Have the page callback transfer the file and check access. Based on file_download().

    function my_module_page_callback() {
      $args = func_get_args(); // Get the path elements after `my-module/download`
      $target = implode('/', $args); // Join them into a string.
      $uri = 'http://some-other-server.com/files/' . $target;
    
    
      if (function_to_check_if_file_exists($uri)) { // Define this function yourself.
        $headers = array('Content-Type' => 'file mime-type'); // Set the correct mime-type for the file here.
    
        if (function_to_check_access()) { // Define this function yourself.
          file_transfer($uri, $headers);
        }
        drupal_access_denied();
      }
      else {
        drupal_not_found();
      }
      drupal_exit();
    }
    

Accessing an url like example.com/my-module/download/documents/1.pdf should now serve a file from http://some-other-server.com/files/documents/1.pdf.

In order to register the files you will have to construct a file object, set the uri to my-module/download/[remote-path] and save the file to the file_managed table. Then attach the file to a node. There might be better ways for this, but this is what I can think of now.

$f = (object) array(
  'uid'         => 1,
  'filename'    => '',
  'uri'         => 'my-module/download/[remote-path]',
  'filemime'    => '',
  'filesize'    => 12345,
  'status'      => 1,
);
file_save($f);

$node = node_load(1);
$node->field_file[LANGUAGE_NONE][0] = (array)$f; // Add a file field on a content type and use the name here.
node_save($node);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.