4.6.x file.incfile_transfer($source, $headers)
4.7.x file.incfile_transfer($source, $headers)
5.x file.incfile_transfer($source, $headers)
6.x file.incfile_transfer($source, $headers)
7.x file.incfile_transfer($uri, $headers)

Transfer file using http to client. Pipes a file through Drupal to the client.

Parameters

$source File to transfer.:

$headers An array of http headers to send along with file.:

Related topics

1 call to file_transfer()

File

 

includes/file.inc, line 923
API for handling file uploads and server file management.

 

Code

function file_transfer($source, $headers) {
  if (ob_get_level()) {
    ob_end_clean();
  }

  // IE cannot download private files because it cannot store files downloaded
  // over HTTPS in the browser cache. The problem can be solved by sending
  // custom headers to IE. See http://support.microsoft.com/kb/323308/en-us
  if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) {
    drupal_set_header('Cache-Control: private');
    drupal_set_header('Pragma: private');
  }

  foreach ($headers as $header) {
    // To prevent HTTP header injection, we delete new lines that are
    // not followed by a space or a tab.
    // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
    $header = preg_replace('/\r?\n(?!\t| )/', '', $header);
    drupal_set_header($header);
  }

  $source = file_create_path($source);

  // Transfer file in 1024 byte chunks to save memory usage.
  if ($fd = fopen($source, 'rb')) {
    while (!feof($fd)) {
      print fread($fd, 1024);
    }
    fclose($fd);
  }
  else {
    drupal_not_found();
  }
  exit();
}

Comments

jpwarren00’s picture

Unlike some other places in Drupal that use an associative array for the header information, 'file_transfer' needs a sequential array. Sorta like this:

file_transfer(file_directory_path().'/'.$filename, array('Content-Type: octet/stream','Content-Disposition: attachment; filename="'.$filename.';',
        'Content-Length: '.filesize(file_directory_path().'/'.$filename),
        ));
nelovishk’s picture

After a lot of trying, I realized that for the first argument, I had to pass the full filesystem path of the file, not just the path relative to base_path(). For example:

<?php
file_transfer($_SERVER['DOCUMENT_ROOT'] . base_path() . file_directory_path() . '/some-file.zip', $headers);
?>
nelovishk’s picture

Maybe it is obvious, but I spent few hours before I realised that the file should be in the file directory of drupal (sites/default/files)... Hope it helps.

nelovishk’s picture

When reading the description of the function, it seems like one can transfer files from any location. It doesn't work that way. One has to dig a little bit in the code, but the issue is this line:

$source = file_create_path($source);

file_create_path() will only accept files in the "files" folder or in the temporary drupal files folder. Files not found there will make the function return false.

vivek.saurabh’s picture

When file transfer is done I need to delete the file or someone wants to do something just after the downloading the file, then in that case what has to done.

来自 https://api.drupal.org/api/drupal/includes%21file.inc/function/file_transfer/6.x