Private Upload
This is an open discussion with 12 replies, filed under Extensions.
Search
Or... put a .htaccess
in the upload folder containing
order allow,deny deny from all
:-)
But it still needs to be accesible for the client (after a login)
@kanduvisla, nice extension. I posted an issue regarding the Remove File action.
I'd also love a more detailed example of how to create the custom event, using this code:
if (file_exists($_GET['file'])) { header('Content-Description: File Transfer'); header('Content-Disposition: attachment; filename='.basename($_GET['file'])); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($_GET['file'])); ob_clean(); flush(); readfile($_GET['file']); exit; } else { die('File does not exist!'); }
What does the $_GET
variable expect? The full path to the file?
Actually, I think I got it:
<?php require_once(TOOLKIT . '/class.event.php'); Class eventdownload_file extends Event{ const ROOTELEMENT = 'download-file'; public $eParamFILTERS = array( ); public static function about(){ return array( 'name' => 'Download File', 'author' => array( 'name' => 'Stephen Bau', 'website' => 'http://www.domain7.com/', 'email' => 'stephen@domain7.com'), 'version' => '1.0', 'release-date' => '2011-05-05T06:02:34+00:00', 'trigger-condition' => 'action[download-file]' ); } public static function getSource(){ } public static function allowEditorToParse(){ return false; } public static function documentation(){ return ' <h3>Download File</h3> <p>Attach this event to a page with a private upload file and use a <code>GET</code>.variable <code>?file=/path/to/filename.ext</code> to download the file.</p> <pre class="XML"><code> <p class="resource-url">Download: <a href="{$current-url}?file={file/@path}/{file/filename}"> <xsl:value-of select="file/filename" /> </a> </p> </code></pre>'; } public function load(){ if(isset($_GET['file'])) return $this->__trigger(); } protected function __trigger(){ if (file_exists($_GET['file'])) { header('Content-Description: File Transfer'); header('Content-Disposition: attachment; filename='.basename($_GET['file'])); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($_GET['file'])); ob_clean(); flush(); readfile($_GET['file']); exit; } else { die('File does not exist!'); } } }
Although a PDF file downloads like this filename.pdf.html
in Safari. :-(
To solve the problem of the .html
extension being appended to file names, I add a Content-Type
header. I wasn't sure how best to send the MIME type, so I just found the file extension and used a switch statement to set the MIME type. The event now looks like this:
<?php require_once(TOOLKIT . '/class.event.php'); Class eventdownload_file extends Event{ const ROOTELEMENT = 'download-file'; public $eParamFILTERS = array( ); public static function about(){ return array( 'name' => 'Download File', 'author' => array( 'name' => 'Stephen Bau', 'website' => 'http://www.domain7.com/', 'email' => 'stephen@domain7.com'), 'version' => '1.0', 'release-date' => '2011-05-05T06:02:34+00:00', 'trigger-condition' => 'action[download-file]' ); } public static function getSource(){ } public static function allowEditorToParse(){ return false; } public static function documentation(){ return ' <h3>Download File</h3> <p>Attach this event to a page with a private upload file and use a <code>GET</code>.variable <code>?file=filename.ext</code> to download the file.</p> <pre class="XML"><code> <p class="resource-url">Download: <a href="{$current-url}?file={file/filename}"> <xsl:value-of select="file/filename" /> </a> </p> </code></pre>'; } public function load(){ if(isset($_GET['file'])) return $this->__trigger(); } protected function __trigger(){ $filename = $_GET['file']; $path = DOCROOT.'/workspace/assets/resources/files/'.$filename; $path_parts = pathinfo($path); $extension = $path_parts['extension']; switch ($extension) { case 'doc': $type = 'application/doc'; break; case 'pdf': $type = 'application/pdf'; break; case 'rtf': $type = 'text/richtext'; break; case 'txt': $type = 'text/plain'; break; } if (file_exists($path)) { header('Content-Description: File Transfer'); header('Content-Disposition: attachment; filename='.$filename); header('Content-Transfer-Encoding: binary'); header('Content-Type: '.$type); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($path)); ob_clean(); flush(); readfile($path); exit; } else { die('File does not exist!'); } } }
And I'm just using the core upload field with an .htaccess
file in the file upload directory:
order allow,deny deny from all ErrorDocument 403 http://www.example.com/forbidden/
And I'm just using the core upload field with an .htaccess file in the file upload directory:
Hi Stephen, does this mean your NOT using the private upload extension here and just a plain old upload field?
Correct. I'm not using the private upload extension. Just the plain old upload field.
Figured! thanks for the code snippet! works a treat! :) Happy New Year
I need to build a site where only members have access to download uploaded files. Problem now is if a user knows the path, they can download. Is it possible with this extension only to allow download from members with approperiate rights? Thanks for the answer.
yes, this extension allows for uploads outside your httpdocs
/public_html
-folder. For members to allow downloading, you can do something like this in a custom event or datasource:
$userIsLoggedIn = someCustomCodeToDetermineIfTheUserIsLoggedInOrNot(); if($userIsLoggedIn) { if (file_exists($_GET['file'])) { header('Content-Description: File Transfer'); header('Content-Disposition: attachment; filename='.basename($_GET['file'])); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($_GET['file'])); ob_clean(); flush(); readfile($_GET['file']); exit; } else { die('File does not exist!'); } }
Anyone interested in helping us creating the custom event? PM info@e-xperience.be
Private Upload
updated to version 1.1
on 15th of May 2012
- Updated for S2.3
Create an account or sign in to comment.
A new extension, "Private Upload" is now available for download. Comments and feedback can be left here but if you discover any issues, please post it on the issue tracker.
Private File Upload
What does this extension do?
Ever asked private data from your visitors in a upload form? Stuff like a resume? Or pictures? Or a copy of their drivers licence? Or do you need to store some data somewhere safe to be sure it doesn't get found or indexed?
Then you'd better make sure to store it properly! Don't store it in your
workspace/uploads
-folder, since that is publicly accessible, but store it on a folder on your server on a lower leven than yourpublic_html
orhttpdocs
-folder. This way, it's not accessible by just entering the URL to it.How does it work?
It's a mod of a regular upload-field, with the difference that instead of selecting a location to store your file, you can enter the exact path on your server, allowing for storing in folders outside of your
public_html
orhttpdocs
.The file is only downloadable in Symphony, when you're logged in, by clicking in the URL in the publish screen.
Please note
public_html
folder. Check your specific host for more information about this.content/content.index.php
for more information on this.