You are here

Drupal8下面私有文件的自主管理技术方案

客户的文件很多,也很大,按照特定的目录进行管理,比如一个期刊下面有很多个PDF文件。如果把所有文件都放到Drupal的文件系统中的话,关联导入都不大方便。

为了解决客户的文件管理,我们只管理某一个期刊的目录,目录下面的文件的下载,展示都通过程序来控制。这个功能在Drupal8下面没有现成的模块。


我们经过讨论,帮助客户定制了一个私有文件的下载管理模块。

需求:


客户自己维护一个私有文件目录,里面的目录结构元信息,整理成csv文件。

只管理目录的信息,一个期刊对应一个目录,这个目录列出期刊的所有可用pdf。

用户查看期刊的时候,可以查看这个期刊下面的所有文件,

点击需要的文件可以下载。下载需要支持统计。


关键代码:

  /**

   * Download list page.

   */

  public function downloadList($resource_type, $resource_id) {

//注意需要修改directory属性,如果设置的不一样,需要修改j_resource,如果不一致。   

$resurce = '';

    $resource = \Drupal::entityManager()->getStorage($resource_type)->load($resource_id);

    if(empty($resource)){

return [

  '#markup' => '<p>' .t('No content.') . '</p>',

];

}

$directory = 'private://' . $resource->directory->value;

    $render_array['content']['files'] = [

          '#type' => 'table',

          '#header' => [

            t('Name'),

            t('Download'),

          ],

        ];

        $rows = [];

    $files = file_scan_directory($directory, '/.*/');

$key = 0;

foreach ($files as $file) {

      $rows[$key]['name'] = $file->filename;

      $rows[$key]['download'] =  new Link(t('download'), Url::fromRoute("mydownload.download", ["resource_type" => $resource_type, "resource_id" => $resource_id, "filename" => $file->filename]));;

      $key++;

    }


    $render_array['content']['files']['#rows'] = $rows;

return $render_array;


  }

  这个函数用来列出期刊的文件。

  

  /**

   * A custom access check.

   *

   * @param \Drupal\Core\Session\AccountInterface $account

   *   Run access checks for this account.

   */

  public function access(AccountInterface $account) {

    // Check permissions and combine that with any custom access checking needed. Pass forward

    // parameters from the route and/or request as needed.

$has_permission = $account->hasPermission('access download page');

$ip = \Drupal::request()->getClientIp();

//if(mydownload_ip_allowed($ip)){

// drupal_set_message('true:' .$ip);

//}else{

// drupal_set_message('false:' .$ip);

//}

//drupal_set_message('id:' .$ip);

if($has_permission || mydownload_ip_allowed($ip)){

  return  AccessResult::allowed();

}

return AccessResult::forbidden();


  }

这个函数用来检查access控制权限,只有有权限的用户,或者特定IP的才可以查看下载。


通过代码控制下载:

  /**

   * Downloads a tarball of the site configuration.

   */

  public function download($resource_type, $resource_id, $filename) {

//注意需要修改directory属性,如果设置的不一样,需要修改j_resource,如果不一致。

    $resource = \Drupal::entityManager()->getStorage($resource_type)->load($resource_id);

    if(empty($resource)){

return [

  '#markup' => '<p>' .t('No content.') . '</p>',

];

}

//$directory = 'private://' . $resource->directory->value;

    $name = $resource->directory->value . '/' . $filename;

    $download = \Drupal::entityTypeManager()->getStorage('download')->create(['filename' => $filename,]);

    //$download->filename->value = '';

    $download->resource_type->value = $resource_type;

$download->resource_id->value = $resource_id;

$download->resource_name->value = $resource->label();

//$download->rid->target_id = $rid;

    $download->ip->value = \Drupal::request()->getClientIp();

    $download->uid->target_id = \Drupal::currentUser()->id();

    $download->timestamp->value = \Drupal::time()->getRequestTime();

$download->save();

    db_merge('mydownload_count')

      //->key('id', $rid)

  ->keys(['id' => $resource_id, 'type' => $resource_type,])

      ->fields([

        'count' => 1,

        'last_timestamp' => \Drupal::time()->getRequestTime(),

      ])

      ->expression('count', 'count + 1')

      ->execute();

  

    $request = new Request(['file' => $name]);

    return $this->fileDownloadController->download($request, 'private');

  } 


这里使用了use Drupal\system\FileDownloadController;管理下载,下载时,统计了哪个用户IP,下载了哪个资源,在什么时间,还对一个资源被下载了多少次进行了计算。


这段代码到这里是不工作的。还需要实现这个钩子函数:

 /**

 * Implements hook_file_download().

 */

function mydownload_file_download($uri) {

  $scheme = file_uri_scheme($uri);

  $filename = drupal_basename($uri);

  if ($scheme == 'private') {


//$filename = $target;

    $disposition = 'attachment; filename="' . $filename . '"';

    return [

      'Content-disposition' => $disposition,

    ];

    //return -1;

  }

}

加上这段关键的代码,就搞定

  


论坛:

Drupal版本: