I'm new to Drupal.

I have a custom form, within a custom module, using Drupal 8.

I would like to provide a simple link (or button, whatever the correct terminology would be), that when a user clicks will download a file that I specify.

  1. How do I create the clickable part in the first place? Is there something like '#type' => 'download', similar to the way '#type' => 'managed_file' is used for uploads? Or is using the 'type' => '#submit' route the best way to go?

  2. Where do I place the file, and how do I make the clickable part grab that file?

The file will be a .xlsx in my case, but I've seen similar questions asking how to do this for a .pdf file, .doc file, etc., but none of them have a concrete answer.

I don't care what the user does with the file once they've downloaded it. It doesn't need to be protected or "read-only" or anything fancy. I just want someone to be able to download the file and save it to their computer.

Code examples would be extremely helpful. So far my best guess is something like this:

// Taxonomy Download
    $form['taxonomy_download'] = [
      '#type' => 'submit',
      '#value' => t('Download Default Taxonomy Terms'),
      '#submit' => array('::downloadFile'),


public function downloadFile() {
     //Get file from /file/path/
     //return $file

Okay, so I found a solution that works pretty well, though I'm sure there are better ways to do this.

I resolved on the submit button approach, as it seems all buttons in Drupal 8 turn into submit buttons anyway. Here's the code for the button itself.

$form['taxonomy_download'] = [
      '#type' => 'submit',
      '#value' => t('Download Default Taxonomy Terms'),
      '#limit_validation_errors' => array(),  //don't run form validation when this button is pressed
      '#submit' => array('::downloadFile'),  //call this function when the button is pressed

Then, for the downloadFile function:

public function downloadFile(array &$form, FormStateInterface $form_state) {

    // Creates a string of the file location. SERVER_NAME returns the
    // name of the host site, e.g. 'www.example.com' or ''
    $buildUrl = 'http://' . $_SERVER['SERVER_NAME'] . '/sites/default/files/Example.xlsx';

    //drupal_set_message($buildUrl);    //uncomment this line to see what is getting passed

    $url = Url::fromUri($buildUrl);     //Creates a url from the file location

    $form_state->setRedirectUrl($url);  //Redirects the user to the file location

You will need to place the file that you're trying to download into the public files folder, found in your Drupal installation's sites/default/files/ folder. You can test that you have the file in the correct location by typing the full path (e.g. http://www.yoursite.com/drupal/sites/default/files/ExampleFile.ext) into your browser's address bar. The file should download when you go to that address.

Finally, you will need to include use Drupal\Core\Url; at the top of your code to make the fromUri() and setRedirectUrl() functions work.

  • Thanks. You had the exact question which i have. The reference is saved file_usage table. how to get the file name and path details from the table? I hope you might have crossed this question.
    – siddiq
    Oct 4 '17 at 3:39

I did like below. Hope it might help someone.

$conn = Database::getConnection();    
$query = $conn->select('file_usage', 'fu')
    ->condition('fu.module', 'mymodule')
    ->condition('fu.type', 'type')
    ->condition('fu.id', $data->id); //$data is a module data i fetched form db
$files = $query1->execute()->fetchAll();
$doclink = Url::fromUserInput('#');//set default as '#' first
if(isset($files[0]) && !empty($files[0])){
    $fid = $files[0]->fid; // Get the file id 
    $file = File::load($fid); //load the file
    $path = $file->getFileUri(); //Get public path
    $filepath =  file_create_url($path); //Get the URL from publi path
    $doclink = Url::fromUri($filepath); //Convert the string to url using fromuri method
//To get the a tag with the url
\Drupal::l('document',$doclink,array('attributes' => array('target'=>'_blank')));

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.