Jump to content

FieldtypeSecureFile


Wanze

Recommended Posts

A ProcessWire Fieldtype storing files in a customized location, outside the web root. This module is primarily useful if you need to store sensitive data which should not be accessible directly from the web. Normally, ProcessWire stores all files under /site/assets/files. Direct URL access to these files can be restriced by setting $config->pagefileSecure = true. Still you need to make sure that your template permissions are setup correctly. If something goes wrong, those files could be accessed from outside.

GitHub: https://github.com/wanze/FieldtypeSecureFile

Modules Directory: http://modules.processwire.com/modules/fieldtype-secure-file/

How does it work?

After installing this module, you can create a new field of type SecureFile. Enter your configuration under the "Details" section when editing the field:

  • Storage Location Enter a path outside the web root where the files are stored. You need to create the directory manually. Also make sure that the user running the web server has write permission.
  • Roles allowing to download a secure file Users with a role selected here are able to download the files if a download is requested via the API.
  • Allow Download in Admin If checked, users having a role selected above can download the files when editing a page.

post-582-0-34938400-1439551190_thumb.png

post-582-0-81382500-1439551207_thumb.png

I needed this functionality for a recent project, so I created this module and thought to share it, mabye this is useful for someone else :) Consider it beta, I'm using it on one site but I'm sure it could be improved here and there. Feel free to suggest additional features!

Cheers

  • Like 22
  • Thanks 1
Link to comment
Share on other sites

I also change line 63 in the module to:

$storageLocation = $this->wire('config')->paths->root.rtrim($field->get('storageLocation'), '/') . '/';

So my secure file path is relative to my web root: eg: ../secure_files/

Which is just one level down from my web root, and is easily configured on most shared hosts.
Just saves a bit of time working out absolute paths on shared accounts.

Might be an option within the module to select "Relative path to Processwire root" or "Absolute Path"

  • Like 4
Link to comment
Share on other sites

Thanks for the feedback guys, I'll look into it.

@Mackski

The option to define the path relative to the root directory makes sense to me, I will add this as an option in the next version.

Cheers

Link to comment
Share on other sites

$secureFile->download(); // Performs the check above and delivers the file via the wireSendFile() function

This opens the file automatically if the page is called. What should be the command to open it only when a link is clicked??

Best regards

Link to comment
Share on other sites

This opens the file automatically if the page is called. What should be the command to open it only when a link is clicked??

I guess you are using the module in the frontend? You will have to implement this logic on your own. A possible solution would be to use a GET variable or a url segment to indicate a download, something like this:

if ($input->get->download == 1) {
  $yourSecureFile->download();
}
Link to comment
Share on other sites

I guess you are using the module in the frontend? You will have to implement this logic on your own. A possible solution would be to use a GET variable or a url segment to indicate a download, something like this:

if ($input->get->download == 1) {
  $yourSecureFile->download();
}

I'm always a bit paranoid, so I check like this:

  // download the secure file
  if($input->get->dl == 1) {
    if($file->name && $file->isDownloadable()) {
      $file->download();
      exit;
    } else {
      // erorr
    }
  }
Link to comment
Share on other sites

@Mackski

Yeah, it's always good to add additional checks. In this situation, $file->isDownloadable() is not necessary, as this check is performed by $file->donwload(). Also ProcessWire's wireSendFile will exit for you if the file was sent :)

Link to comment
Share on other sites

Is there a possibility to get the size of the file?

Usually I get the filesize like this:

$file       = "path-to-the-file";
$filesize   = (filesize($file) * .0009765625) * .0009765625; // bytes to MB
$filesize   = round($filesize, 2);//rounding 

But in this case it is not possible to use the path to the file.

Link to comment
Share on other sites

Is there a possibility to get the size of the file?

Usually I get the filesize like this:

$file       = "path-to-the-file";
$filesize   = (filesize($file) * .0009765625) * .0009765625; // bytes to MB
$filesize   = round($filesize, 2);//rounding 

But in this case it is not possible to use the path to the file.

I am sure Wanze will be able to offer up a solution to get the filesize from the path. I just wanted to chime in with a nice function for converting to human readable filesizes: http://jeffreysambells.com/2012/10/25/human-readable-filesize-php

function human_filesize($bytes, $decimals = 2) {
   $size = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
   $factor = floor((strlen($bytes) - 1) / 3);
   return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$size[$factor];
}
  • Like 4
Link to comment
Share on other sites

It's ProcessWire :) Use:

$pageFile->filename; // Path & Filename
$pageFile->basename; // Filename without path
$pageFile->filesize; // Size in bytes
$pageFile->filesizeStr; // Human readable Filesize
  • Like 3
Link to comment
Share on other sites

It's ProcessWire :) Use:

$pageFile->filesizeStr; // Human readable Filesize

only issue is i would want the file size to display like 2.97MB but it displays 3,044 kB  using filesizeStr- should i use Adrian's proposed function? would be cool of you could pass some option to filesizeStr to show in MB

Link to comment
Share on other sites

only issue is i would want the file size to display like 2.97MB but it displays 3,044 kB  using filesizeStr- should i use Adrian's proposed function? would be cool of you could pass some option to filesizeStr to show in MB

Thanks for reminding me why I didn't use filesizeStr :)

Link to comment
Share on other sites

Only to mention:

$pageFile->filename; // Path & Filename
$pageFile->basename; // Filename without path
$pageFile->filesize; // Size in bytes
$pageFile->filesizeStr; // Human readable Filesize

This only works if the number of files is set to 1. If it is unlimited (0) only the PW short syntaxes for files (more than 1) work. I ran also into this mistake and I wondered why I didnt got a result.

Maybe you have to use an foreach loop if you have more than 1 file (I have not tried it).

Link to comment
Share on other sites

  • 3 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...