Protect PDF files? possible?


Is it possible to protect direct file access when using the private login section for pages in grav?


Not to my knowledge. There’s a Private plugin that will protect pages, but that won’t stop direct access to other files. Though not documented, there is a onBeforeDownload event that a plugin could conceivably bind to. You’d have to do some testing.

I Fixed this by protect the download directory with a .htaccess and let php do the pdf download handling (and checking if the user has logged in)

btw thx for your answer, i have not tested that function before

Could you provide your solution, i have the same issue, trying to protect files. Thank you!

Grav’s Login plugin has an option (in login.yaml) protect_protected_page_media that’s set to false by default. When you set it to true, it will redirect to the login page when trying to access pdf’s in protected folders.

There’s also parent_acl option that “allows you to create private areas where you set the access level on the parent page, and all the subpages inherit that requirement.”

i don’t have login plugin, i just want to know how @raack made download function with php and .htaccess and where files stores. I need this function from several pages and i want to hide my files from search engine.

Hi @kirill_01,

Somehow i posted a whole example, but it disappeared? Sorry for my late reaction;

i have placed a htaccess in my downloads directory with a rule to ignore pdf’s from direct linking;

RewriteCond %{THE_REQUEST} \.pdf[?\s] [NC]

then i have made a custom plugin for downloading pdf’s;

// url for handling pdf's
protected pdfURL = "/pdf";
protected downloadFolder = "downloads";

in the function onPluginsInitialized i have this following code

        if ($this->pdfURL && $this->pdfURL == $uri->path()) {
                'onPagesInitialized' => ['getPDF', 0]

so, if i request the url with a link like

Download PDF

then in my function getPDF you can do something like:

public function getPDF() {

     $uri = $this->grav['uri'];
     $ref = !empty($_POST['ref']) ? $_POST['ref'] : $uri->param('ref');

    //check if user has logged in, or whatever :-)
    if($this->grav['user']->authenticated && isset($ref)) {

        $path = ROOT_DIR . $this->downloadFolder . '/' . $ref;

        if(!file_exists($path)) {
            die("No file here");
        header("Content-Disposition: inline; filename=".$ref);
        header("Content-type: application/pdf");
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Pragma: no-cache');
            $fp = fopen($path, 'rb');
    } else { 


In your case you can check it by a valid user session or something.
Hope this works for you.