hintraeger Posted February 7 Share Posted February 7 I would like to protect files (pdf) that are located in the site/assets/files folder from being downloaded directly via the url that leads to this file. However, when a page containing the file field is called up, it must be possible to make this file available for download. Is there a solution for this in processwire. The access should be controlled depending on the role of the current user and another parameter. I tried it like this: I have protected the folder site/assets/files with .htaccess file: <FilesMatch "\.(pdf)$"> <IfModule mod_authz_core.c> Require all denied </IfModule> <IfModule !mod_authz_core.c> Order allow,deny Deny from all </IfModule> </FilesMatch> Then created a template that makes the file path available for download as follows: <?php if( $ok ) { header("Content-type:application/pdf"); header("Content-Disposition:attachment;filename=$downloadname" ); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0,pre-check=0"); header("Pragma: public"); readfile("/var/www/...".$download); } This works perfectly in a test php file, but when integrated via a template file in processwire it does not work. My guess is that a header is delivered by processwire, a different content-type or something like that. In the template I have tried contentType application/pdf and empty, neither works. Link to comment Share on other sites More sharing options...
hintraeger Posted February 7 Author Share Posted February 7 sorry i have forgot something. The download works, but the downloaded file is defect: Acrobat Reader reports: An error occurred while opening this document. This file is damaged and cannot be repaired. Outside processwire with the same procedure in pure php the same downloaded file is ok. Link to comment Share on other sites More sharing options...
cwsoft Posted February 7 Share Posted February 7 The line with the readfile command has three dots at the end which seems strange to me and then adds whatever is your $download variable. Have you checked that path e.g. via outputin template and checked if file is readable? Link to comment Share on other sites More sharing options...
BrendonKoz Posted February 7 Share Posted February 7 Have you tried the template settings for file-level access control? It might not be exactly what you want (without some fiddling), but it's what currently seems the closest thing to what you're looking for. 1 Link to comment Share on other sites More sharing options...
hintraeger Posted February 7 Author Share Posted February 7 40 minutes ago, cwsoft said: The line with the readfile command has three dots at the end which seems strange to me and then adds whatever is your $download variable. Have you checked that path e.g. via outputin template and checked if file is readable? ... is just a placeholder, I have removed the correct path. The file with the correct file size is downloaded, but it is broken. But if I download the same file outside of processwire in the same way, then the file is OK. Link to comment Share on other sites More sharing options...
hintraeger Posted February 7 Author Share Posted February 7 8 minutes ago, BrendonKoz said: Have you tried the template settings for file-level access control? It might not be exactly what you want (without some fiddling), but it's what currently seems the closest thing to what you're looking for. Thanks, yes I tried that too, but unfortunately it's not quite what I need. Link to comment Share on other sites More sharing options...
dynweb Posted February 7 Share Posted February 7 Have you checked that there are no files prepended/appended when rendering the template? Maybe disable Tracy debugger? Link to comment Share on other sites More sharing options...
hintraeger Posted February 8 Author Share Posted February 8 11 hours ago, dynweb said: Have you checked that there are no files prepended/appended when rendering the template? Maybe disable Tracy debugger? I have no files prepended/appended and tracy debuger is also disabled. But I know the problem now. The downloaded file is only unreadable on my older Mac by Acrobat, Preview and Safari. In Brave it is and on newer operating system versions there is also no problem. The pdf must have been altered somehow so that it is no longer compatible with older pdf readers. A bit strange. But it would be nice if processwire had a solution here on how to prevent the download of files directly via an url link. Maybe there is already such a solution and I just don't know it. I think there was a solution in drupal. There you could decide whether the files should be stored in a directory outside the web directory and thus be protected from direct access. Unfortunately I don't know how the download was solved via a template. It would be great if there was a solution in the future. Many thanks for your answers. Link to comment Share on other sites More sharing options...
netcarver Posted February 8 Share Posted February 8 @hintraeger Have you taken a look at the pagefileSecure config option? Might not be suiteable for you, but for file storage outside the site root, how about @Wanze's FieldtypeSecureFile module? I also remember there being a very old post from @Soma here in the forum about this topic. Link to comment Share on other sites More sharing options...
cwsoft Posted February 8 Share Posted February 8 Have you tried Content-Type: application/pdf (with space after colon)? Does it work with PW if you remove the .htaccess file? Have you tried different PDF and different browsers too? Link to comment Share on other sites More sharing options...
Jim Bailie Posted February 8 Share Posted February 8 FWIW -- I have a template called "downloads". When someone goes to https://example.com/downloads/specialfilename.php, the file name is treated as a url segment. From the url segment, I will essentially: Search for the file Make sure it's there Then deliver it via the mime process // Get page ($p) where the file lives // Still here, so lets see if we can get the actual file $file = $p->filesManager->getFile($fileNameSanitized); if(!$file) return 'File not found(3)'; header("Content-Type: application/pdf"); header("Content-Disposition: inline; filename=$fileName"); header("Content-Transfer-Encoding: binary"); header("Accept-Ranges: bytes"); @readfile($file->filename); return true; 2 Link to comment Share on other sites More sharing options...
gebeer Posted February 9 Share Posted February 9 Code here: and here: might be helpful. This implementation is working for me on several projects. 1 Link to comment Share on other sites More sharing options...
hintraeger Posted February 22 Author Share Posted February 22 On 2/9/2024 at 7:53 AM, gebeer said: Code here: and here: might be helpful. This implementation is working for me on several projects. thank you, that is exactly what i searched for 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now