PHP users file uploads ( I need some help please )

Thor

Honorary Master
Joined
Jun 5, 2014
Messages
44,413
Reaction score
7,522
Location
Bellville
Hi,

Can someone please give me some guidance, I have a simple Create an account section that when the user creates and account he can then login and when he is logged in he then gets access to the logged in pages.

I want to add the ability on one page for the logged in user to be able to upload a pdf.

Here is where my issue comes i;

#1 How do I prevent other users and people from seeing it, because if I put all file uploads in the directory /upload then I assume anyone can simply type that in and view all the info.

#2 How can I create an admin side for me to view the user and then the file he uploaded?

==========
Currently my code is as follows on the logged in viewable pages.

PHP:
<?php
include_once 'dbconfig.php';
if(!$user->is_loggedin())
{
	$user->redirect('index.php');
}
$user_id = $_SESSION['user_session'];
$stmt = $DB_con->prepare("SELECT * FROM users WHERE user_id=:user_id");
$stmt->execute(array(":user_id"=>$user_id));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="keywords" content="">
    <meta name="copyright" content="">
    <meta name="author" content="">
    <!-- Latest compiled and minified CSS -->
    <title>Welcome - <?php print($userRow['user_email']); ?> | Reseller Protected Document</title>
    ...
    ...
    ...

dbconfig.php is as follows:
PHP:
<?php

session_start();

$DB_host = "localhost";
$DB_user = "root";
$DB_pass = "";
$DB_name = "dblogin";

try
{
	$DB_con = new PDO("mysql:host={$DB_host};dbname={$DB_name}",$DB_user,$DB_pass);
	$DB_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
	echo $e->getMessage();
}


include_once 'class.user.php';
$user = new USER($DB_con);

class.user.php is a follows:
PHP:
<?php
class USER
{
	private $db;
	
	function __construct($DB_con)
	{
		$this->db = $DB_con;
	}
	
	public function register($fname,$lname,$uname,$umail,$upass)
	{
		try
		{
			$new_password = password_hash($upass, PASSWORD_DEFAULT);
			
			$stmt = $this->db->prepare("INSERT INTO users(user_name,user_email,user_pass) 
		                                               VALUES(:uname, :umail, :upass)");
												  
			$stmt->bindparam(":uname", $uname);
			$stmt->bindparam(":umail", $umail);
			$stmt->bindparam(":upass", $new_password);										  
				
			$stmt->execute();	
			
			return $stmt;	
		}
		catch(PDOException $e)
		{
			echo $e->getMessage();
		}				
	}
	
	public function login($uname,$umail,$upass)
	{
		try
		{
			$stmt = $this->db->prepare("SELECT * FROM users WHERE user_name=:uname OR user_email=:umail LIMIT 1");
			$stmt->execute(array(':uname'=>$uname, ':umail'=>$umail));
			$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
			if($stmt->rowCount() > 0)
			{
				if(password_verify($upass, $userRow['user_pass']))
				{
					$_SESSION['user_session'] = $userRow['user_id'];
					return true;
				}
				else
				{
					return false;
				}
			}
		}
		catch(PDOException $e)
		{
			echo $e->getMessage();
		}
	}
	
	public function is_loggedin()
	{
		if(isset($_SESSION['user_session']))
		{
			return true;
		}
	}
	
	public function redirect($url)
	{
		header("Location: $url");
	}
	
	public function logout()
	{
		session_destroy();
		unset($_SESSION['user_session']);
		return true;
	}
}
?>

Side note:

If you need other code, please let me know and I will edit to show the relative code.
 
Have a look here: http://webcheatsheet.com/php/file_upload.php
The "upload" directory should/could be outside of the document root.
So, if the server is apache, and your html/php files is located in /srv/www/htdocs, then you could save the uploaded files to /srv/www/uploads.
PHP will be able to access these files, but nobody would be able to see it without going through your wrapper php file.
I would keep a DB table that keeps track of user and filename.
 
Turn off Directory Listing.

And display the contents of the folder, to those who have access to it, via a PHP page of some or other description.
 
I am so lost currently the only thing I have figured out is how to make only members access certain sections using this:

PHP:
<?php
include_once 'dbconfig.php';
if(!$user->is_loggedin())
{
    $user->redirect('index.php');
}
$user_id = $_SESSION['user_session'];
$stmt = $DB_con->prepare("SELECT * FROM users WHERE user_id=:user_id");
$stmt->execute(array(":user_id"=>$user_id));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
?>

What I have no idea how to do is make a page that when the signed in user uploads the file it will be linked to that user.

Viewable in that users account and also viewable by Admin.

Scenario I want to add the ability for a user to upload proof of payment and then I want to get a notification and then have the ability to view said user's proof of payment.
 
I am so lost currently the only thing I have figured out is how to make only members access certain sections using this:

PHP:
<?php
include_once 'dbconfig.php';
if(!$user->is_loggedin())
{
    $user->redirect('index.php');
}
$user_id = $_SESSION['user_session'];
$stmt = $DB_con->prepare("SELECT * FROM users WHERE user_id=:user_id");
$stmt->execute(array(":user_id"=>$user_id));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
?>

What I have no idea how to do is make a page that when the signed in user uploads the file it will be linked to that user.

Viewable in that users account and also viewable by Admin.

Scenario I want to add the ability for a user to upload proof of payment and then I want to get a notification and then have the ability to view said user's proof of payment.

Store the filename + path + username in the Database...
 
Will this work if I try to write the code to do the following;

When a user registered the php should create a folder in the directory "Users" using the email

Then when said user uploads the file I use the following in the upload script:


PHP:
// Where the file is going to be placed 
$target_path = "uploads/<?php $userRow['user_email']); ?>";
 
No reason why that wouldn't work.

I would rather user the user's username for the folder name.
 
No reason why that wouldn't work.

I would rather user the user's username for the folder name.

Thought about username, but I want to use something that is #1 unique and #2 that will be used as a reference.

Becuase my idea now is to be able to view that folder and it's content.

So essentially pop.example.com ( pop = proof of payment )

Then the pop.example.com will allow me(admin) to log in and then display all the folders and I want to filter so lets say there is 500 folders

I want to type in [email protected] for instance and then I see his folder, open it up and bam! Pop is there for me to retrieve.
 
Now I need some guidance how to add this into my registration script

I was thinking of using this;
PHP:
mkdir("/path/to/my/[umail]", 0700);

In here;

PHP:
<?php
class USER
{
	private $db;
	
	function __construct($DB_con)
	{
		$this->db = $DB_con;
	}
	
	public function register($fname,$lname,$uname,$umail,$upass)
	{
		try
		{
			$new_password = password_hash($upass, PASSWORD_DEFAULT);
			
			$stmt = $this->db->prepare("INSERT INTO users(user_name,user_email,user_pass) 
		                                               VALUES(:uname, :umail, :upass)");
												  
			$stmt->bindparam(":uname", $uname);
			$stmt->bindparam(":umail", $umail);
			$stmt->bindparam(":upass", $new_password);										  
				
			$stmt->execute();	
			
			return $stmt;	
		}
		catch(PDOException $e)
		{
			echo $e->getMessage();
		}				
	}
	
	public function login($uname,$umail,$upass)
	{
		try
		{
			$stmt = $this->db->prepare("SELECT * FROM users WHERE user_name=:uname OR user_email=:umail LIMIT 1");
			$stmt->execute(array(':uname'=>$uname, ':umail'=>$umail));
			$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
			if($stmt->rowCount() > 0)
			{
				if(password_verify($upass, $userRow['user_pass']))
				{
					$_SESSION['user_session'] = $userRow['user_id'];
					return true;
				}
				else
				{
					return false;
				}
			}
		}
		catch(PDOException $e)
		{
			echo $e->getMessage();
		}
	}
	
	public function is_loggedin()
	{
		if(isset($_SESSION['user_session']))
		{
			return true;
		}
	}
	
	public function redirect($url)
	{
		header("Location: $url");
	}
	
	public function logout()
	{
		session_destroy();
		unset($_SESSION['user_session']);
		return true;
	}
}
?>

Any ideas how to do this correctly? Would be much appreciated
 
You users table probably have a unique ID column as well. You could use this together with the username, or on its own to create the directory.
 
Upload files to a folder while keeping track of files in a database table. Row in DB should correlate with User table.

Then SELECT * FROM Files WHERE UserID = $LoggedInUserID
 
You users table probably have a unique ID column as well. You could use this together with the username, or on its own to create the directory.
I do have a unique ID yes.

Upload files to a folder while keeping track of files in a database table. Row in DB should correlate with User table.

Then SELECT * FROM Files WHERE UserID = $LoggedInUserID

Sounds wonderful, but I am a noob I will need some code (:
 
I'm not sure what the problem is - unless your design is deeply flawed usernames should be unique. just use those.

What ^^vampire^^ is say is:

When the user uploads the a file you should store (in a separate table) the username and file path.

Then when you want just that user's files to be displayed you will select from the UserPaths table where userid = $UserId.
 
I'm not sure what the problem is - unless your design is deeply flawed usernames should be unique. just use those.

What ^^vampire^^ is say is:

When the user uploads the a file you should store (in a separate table) the username and file path.

Then when you want just that user's files to be displayed you will select from the UserPaths table where userid = $UserId.

Okey I see what you mean! If I wanted to do it like that then username would be the best.

I simply suggested the email because a user will communicate with us via email so it's just easier to use than to ask a user for his username via email and then his user name is DarthSuckSomePenisFader87 where is all i could have done was simply search by email which we have.

I hope that clears it up a little bit why I want to use email instead of username for the file directories. They can however log in with either mail or Username of course.

Okey back to track:

I need someone to assist me with my code to actually insert the part into class.users.php that will enable the directory to be created upon registration.

Or the code to do this whole link to database thing, but that sounds a lot more over complicating things compared to the example I outlined above?
 
your users have an id which should never change, they may change their email at some time ...

User table:
id,
email,
name,
...

Then have a files/documents/whatever table similar to:
id integer,
user_id integer,
document_name varchar,
filename varchar,
mime_type varchar,
...

So, something like this:

Code:
public function store_document($document_name, $filename,$mime_type,...)   //... - any other field you want to save ..
    {
        try
        {
            
            $stmt = $this->db->prepare("INSERT INTO files(user_id,document_name,filename, mime_type, ....) 
                                                       VALUES(:user_id, :document_name, :filename, :mime_type, ....)");
                                                  
            $stmt->bindparam(":user_id", $this->id);  //$this->id should refer to the current users ID 
            $stmt->bindparam(":document_name", $document_name);
            $stmt->bindparam(":filename", $filename);                                          
            $stmt->bindparam(":mime_type", $mime_type);                                          
            ......
                
            $stmt->execute();    
            
            return $stmt;    
        }
        catch(PDOException $e)
        {
            echo $e->getMessage();
        }                
    }
 
your users have an id which should never change, they may change their email at some time ...

User table:
id,
email,
name,
...

Then have a files/documents/whatever table similar to:
id integer,
user_id integer,
document_name varchar,
filename varchar,
mime_type varchar,
...

So, something like this:

Code:
public function store_document($document_name, $filename,$mime_type,...)   //... - any other field you want to save ..
    {
        try
        {
            
            $stmt = $this->db->prepare("INSERT INTO files(user_id,document_name,filename, mime_type, ....) 
                                                       VALUES(:user_id, :document_name, :filename, :mime_type, ....)");
                                                  
            $stmt->bindparam(":user_id", $this->id);  //$this->id should refer to the current users ID 
            $stmt->bindparam(":document_name", $document_name);
            $stmt->bindparam(":filename", $filename);                                          
            $stmt->bindparam(":mime_type", $mime_type);                                          
            ......
                
            $stmt->execute();    
            
            return $stmt;    
        }
        catch(PDOException $e)
        {
            echo $e->getMessage();
        }                
    }

I love you Sir! I really do.
 
As was mentioned before - you store the files in a directory outside of the webroot and have a function to save and a function to retrieve the documents.
The function should accept a user id and a document id.

The document id can come from the frontend ( a webpage with a list of the users documents) but the user id should come from your $_SESSION variable (I assume that when the user logs in you are storing their id somewhere). You should NOT be accepting the user id from the frontend.

If you do accept the user id and document id from the frontend then someone can alter your html and send through their own values for the id and document, eventually getting 'illegal' access to all your documents.
 
Top
Sign up to the MyBroadband newsletter
X