Jump to content

Archived

This topic is now archived and is closed to further replies.

me1000

image hosting

Recommended Posts

ok, i have created a php script (one file) that will upload an image.

to do this the user must first create an account and then the admin would have to enable the user to upload iamges.

the admin (me) would then create a directory called whatever the users name was.

the problem is I do not know how to limit the amount of space the user has.

please help!

Thanks,
Me1000

Share this post


Link to post
Share on other sites
I'm pretty sure the only way to do with entirely through php is to loop through all the files in the directory every time a file wants to be uploaded, add all the filesizes together into a variable, subtract that from your max size allowed, then subtract the filesize of the uplaoded image from that. If you end up with a number <= 0, you don't have enough space.

Share this post


Link to post
Share on other sites
you sound like php is not the way to go about this, how would you do it?

Share this post


Link to post
Share on other sites
It all depends on the operating system and web server and the ammount of access you have to it.

Share this post


Link to post
Share on other sites
xyph is correct, there is no "direct" way of knowing the directory's space.

However, if all the files are uploaded and stored through PHP, you can recalculate the size of the directory each time a file is uploaded / deleted.

Save this information in a file and voilá, you can retrieve the space used by him/her whenever you need.

[b]EDIT:[/b] This sounds interesting. I'll code something and post it in a while.

Share this post


Link to post
Share on other sites
Another possible solution would be to have a table in your mysql database something like this,

file_size, file_owner

File size would be an int and so would file owner, obviously file owner would be the key value from the user table identifying the user. Anyway, upon uploading the file successfully you would take the value $file_size that you got during the process and the value $user_id also retrieved during the upload and add them both to the table.

Each time a person attempts to upload a file the database is queried first and the file_size values are summed, if they exceed a $max_size value you specify then you drop an error message on them, else upload.

Share this post


Link to post
Share on other sites
Buyocat i like the mysql idea. if a user would hapen to deleate a file, is there a way php can get the file size of it before it is removed?

my host is using redhat enterprise and as for access I have the ablility to uplaod anything I want, thats about it. i can shell into it. if I had an idea of what you were trying to do i could tell you if its posible!

Share this post


Link to post
Share on other sites
Buyocat has a great idea here, and IMO would be the best way to do it. Store the size and the owner in a DB, when they delete the file, also delete the entry.

Share this post


Link to post
Share on other sites
ok i think ill try that.

chances are im going to need more help, so ill probably be back with some code!

Share this post


Link to post
Share on other sites
When you say that a user deletes a file, do you mean through PHP and the browser? If not then sadly I'm not sure how that could be automatically tallied in the database. Still, what sort of problem are you trying to solve where users can come and delete files through FTP but have to add them through the browser?


At any rate this is what I would suggest
1. Create a table with 2 columns: file_id file_size and file_owner (file owner will hold the unique ID of a user)
2. Make a script that queries the table and gets all the file_sizes for a specific file_owner and sums them
3. In the same script check that sum against a max size you outline
4. Make an upload file script that executes after #3 passes
5. Make a script that enters in the file size of the file in #4 and the user id of the owner
6. Make a script using rename() that moves a file a user specifies to a "trash" folder you make
7. Make a query that removes the entry from the table where file_id and user_id are matched
8. Every once in a while (cron job) you check up on that trash folder and empty it yourself

I hope that is straightforward enough, you can read more about rename here,
[a href=\"http://us3.php.net/manual/en/function.rename.php\" target=\"_blank\"]http://us3.php.net/manual/en/function.rename.php[/a]

Share this post


Link to post
Share on other sites
[a href=\"http://www.php.net/disk_total_space\" target=\"_blank\"]http://www.php.net/disk_total_space[/a]

Might also be worth looking in to (does eating my own words usually taste this bad?)

Share this post


Link to post
Share on other sites
[!--quoteo--][div class=\'quotetop\']QUOTE[/div][div class=\'quotemain\'][!--quotec--]Given a string containing a directory, this function will return the total number of bytes on the corresponding filesystem or disk partition.[/quote]

Share this post


Link to post
Share on other sites
Guys, I think that might be overkill or waste of resources, especially if you begin to store each file's size and everything in a MySQL database.

From what I see, he just needs something that will limit / report disk usage. So I coded something easy

[code]<pre>
<?php

// This is a function that will get the directory's size
// It WILL NOT scan deep into it's subdirectories though
function getDirSize($dir)
{

   if (!is_dir($dir)) {
      return false;
   }

   if (strrpos($dir, '/') !== strlen($dir)) {
      $dir .= '/';
   }
  
   $files = scandir($dir);
   $size = 0;

   for ($i=0; $i<count($files); $i++) {
      if (is_file($dir . $files[$i]) && $files[$i] != 'usage.txt') {
         $size += filesize($dir . $files[$i]);
      }
   }

   return $size;
}

// I am setting the directory here - to where information will be uploaded.
$dir = './dir/';

// This is the destination file name
// I recommend you to specify a full path, like what I am doing here
$dest = $_SERVER['DOCUMENT_ROOT'] . '/helps/upload/'. $dir . basename($_FILES['file']['name']);

// Here I am retrieving the usage
$size = (int) file_get_contents($dir . 'usage.txt');

// PHP here is overwriting existing files
// This is why I need to subtract the size of an existing file
if (is_file($dest)) {
   $size -= filesize($dest);
}

// This handles the upload.
if (move_uploaded_file($_FILES['file']['tmp_name'], $dest)) {

   // Adding up the new file's size
   $size += $_FILES['file']['size'];
  
   // Recording to the FlatFile
   $handle = f.open($dir . 'usage.txt', 'w+');
   @f.write($handle, $size);
   @f.close($handle);

   echo "File successfully uploaded.\r\n";
   echo "Current usage: $size bytes.\r\n";

} else {
   echo "Upload Failed!\r\n";
}

// Retrieving the current usage:
echo "\r\n==============================\r\n";
// This one gives you the SIZE of the folder
echo "\r\n" . 'Folder size: ' . getDirSize($dir) . ' bytes';

// This one gives you the recorded USAGE
echo "\r\n" . 'Usage: ' . $size . ' bytes';

// Below, the upload form
?>

</pre>

<form enctype="multipart/form-data" action="" method="post">
   Send this file: <br /><input name="file" type="file" /><br />
   <input type="submit" value="Send File" />
</form>[/code]

[!--coloro:blue--][span style=\"color:blue\"][!--/coloro--]There are 2 ways of retrieving the used space.[!--colorc--][/span][!--/colorc--].

1. The script will record the usage based on files uploaded through the script and store it in the usage.txt (value in bytes). Just use file_get_contents($dir . 'usage.txt') to retrieve it.

For this to work, create a file called usage.txt and put it into each folder.

2. I coded also another function, to get the usage of certain directory. It will give you the size of files under it; no matter they were uploaded by PHP or not. This might be pretty useful since you won't need to recalculate usage whenever files are uploaded/deleted.

More details are in the comments. Also, remember to remove the dots from f.open, f.write and f.close when using the code.

Share this post


Link to post
Share on other sites
ill try that out! thanks ill post here with an update!

Share this post


Link to post
Share on other sites
me1000, you might want to read my post again since it may've been edited.

xyph, disk_total_space() won't be useful I guess.

Share this post


Link to post
Share on other sites
I was referring more to the user comments in that function.

Share this post


Link to post
Share on other sites
ok tell me if i edited this correctly.

[code]<pre>
<?php
include("../../inlcude/session.php");
// This is a function that will get the directory's size
// It WILL NOT scan deep into it's subdirectories though
//$dir = "uploads/".$session->username

function getDirSize($dir)
{

   if (!is_dir($dir)) {
      return false;
      echo "you do not a have directory to upload to, please contact webmaster";
   }

   if (strrpos($dir, '/') !== strlen($dir)) {
      $dir .= '/';
   }
  
   $files = scandir($dir);
   $size = 0;

   for ($i=0; $i<count($files); $i++) {
      if (is_file($dir . $files[$i]) && $files[$i] != 'usage.txt') {
         $size += filesize($dir . $files[$i]);
      }
   }

   return $size;
}

// I am setting the directory here - to where information will be uploaded.
$dir = 'uploads/'$session->username;

// This is the destination file name
// I recommend you to specify a full path, like what I am doing here
$dest = $_SERVER['DOCUMENT_ROOT'] . '/htdocs/www/special/tutorials/'. $dir . basename($_FILES['file']['name']);

// Here I am retrieving the usage
$size = (int) file_get_contents($dir . 'usage.txt');

// PHP here is overwriting existing files
// This is why I need to subtract the size of an existing file
if (is_file($dest)) {
   $size -= filesize($dest);
}

// This handles the upload.
if (move_uploaded_file($_FILES['file']['tmp_name'], $dest)) {

   // Adding up the new file's size
   $size += $_FILES['file']['size'];
  
   // Recording to the FlatFile
   $handle = f.open($dir . 'usage.txt', 'w+');
   @f.write($handle, $size);
   @f.close($handle);

   echo "File successfully uploaded.\r\n";
   echo "Current usage: $size bytes.\r\n";

} else {
   echo "Upload Failed!\r\n";
}

// Retrieving the current usage:
echo "\r\n==============================\r\n";
// This one gives you the SIZE of the folder
echo "\r\n" . 'Folder size: ' . getDirSize($dir) . ' bytes';

// This one gives you the recorded USAGE
echo "\r\n" . 'Usage: ' . $size . ' bytes';

// Below, the upload form
?>

</pre>

<form enctype="multipart/form-data" action="" method="post">
   Send this file: <br /><input name="file" type="file" /><br />
   <input type="submit" value="Send File" />
</form>[/code]

I just ran the script and im getting...
[!--quoteo--][div class=\'quotetop\']QUOTE[/div][div class=\'quotemain\'][!--quotec--]Parse error: parse error, unexpected T_VARIABLE in /htdocs/www/special/tutorials/upload2.php on line 33[/quote]

line 33 is
[code]$dir = 'uploads/'$session->username;
[/code]

Share this post


Link to post
Share on other sites
Change it to
[code]$dir = 'uploads/' . $session->username;[/code]

Also, you may be including the wrong file:
[!--quoteo--][div class=\'quotetop\']QUOTE[/div][div class=\'quotemain\'][!--quotec--]include("../../[b]inlcude[/b]/session.php");[/quote]

[b]EDIT:[/b] I guess you initialized the session class properly, or you will get ugly errors like "Trying to get property of non-object" (if notices are reported), or it will work, but $session->username will be just blank.

Share this post


Link to post
Share on other sites
yeah the session.php file is right.

now im getting this page.
[!--quoteo--][div class=\'quotetop\']QUOTE[/div][div class=\'quotemain\'][!--quotec--]Upload Failed!

==============================


Fatal error: Call to undefined function: scandir() in /htdocs/www/special/tutorials/upload2.php on line 20

[/quote]

Share this post


Link to post
Share on other sites
Not good... It happened because scandir was added as of PHP5...
This forces me to code a custom function, but here it goes:

[code]// Custom scandir function
function c_scandir($dir)
{
   if (function_exists('scandir')) {
      return scandir($dir);
   }
  
   $files = array();
  
   if ($handle = opendir($dir)) {
      while (false !== ($file = readdir($handle))) {
          $files[] = $file;
      }
      closedir($handle);
   }
   return $files;
}[/code]

Then, just add this function in your code (prior to it's call obviously) and change the line:

[code]   $files = scandir($dir);[/code]
To
[code]   $files = c_scandir($dir);[/code]

And it should work.

Share this post


Link to post
Share on other sites
thanks, I do have php 5 installed on the server, but i have to name the file filename.php5 in order for it to work!

im not getting the error message anymore, but i still cant upload!

Share this post


Link to post
Share on other sites
Just add something to check it ... Like:

[code]$size = (int) file_get_contents($dir . 'usage.txt');

if ($size => (10*1024*1024)) {
   die ("Wooops, size exceeded");
}[/code]

What happens when you try to upload? Did it work before?
Did you set the correct CHMOD for the folder(s)?

Share this post


Link to post
Share on other sites
no the upload part of it has never worked.

who i added the code you gave me it gave me a blank screen. im not sure where i should add it. and then how would i use the else part of that if statment?

cmod settings are fine also.

from what i have posted can you tell me where the images would be uploaded to,
htdocs/www/special/tutorials/uploads/username

thats what it should be.

then you can get to that by going to
www.site.com/special/tutorials/uploads/username/image.jpg

edit: i echo'ed the dir variable
and it read
[!--quoteo--][div class=\'quotetop\']QUOTE[/div][div class=\'quotemain\'][!--quotec--]uploads//[/quote]
it ignoring the
$session->username

Share this post


Link to post
Share on other sites
ok i have edited the code to replace $sesson->username.
now i still cant upload but something did change

Folder size: 37546 bytes

it used to say zero
Usage: still says zero though.

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.