storing too many files in a single directory can lead to problems. not only performance will suffer at a certain point, but a friend (with way more experience than me) told me that some backup programs have problems with this.
so when i had to store thousands of images i always created 256 subdirectories, and stored the files in the directory files/{id mod 256}/{myfile_id}.jpg
to protect yourself against hackers there are a lot of things to do, and nothing will be safe (because hackers will most likely try to get root access and then your data isn't safe anyway).
1) so ... regular backups. period.
2) audit log files (who what when). that's not security per se, but may help you in discovering security holes and fix bugs
3) set the file permissions accordingly (important on shared servers without chroot-ing)
4) double-check if an action really is done by the right user. it must be impossible to do harm by guessing the url.
there's more if you want to make the filenames and -paths secret. e.g. it's possible to not directly link to the image, but to a script that serves that image. in this case you're able to store the files outside the webroot (additionally, your more independent of filenames) (see code at the end).
one more step would be to avoid auto_increment id values to identify images. better use an unique hash (md5(mt_rand());
) without a correlation to the id and store that in the database (afaik youtube and flickr do that).
ugly php-pseudocode for passing through would be something like:
<?php
if (isset($_REQUEST['img'])) {
$hash = $_REQUEST['img']);
if (($res = getImageByHash($hash)) !== false) {
list($id, $name, $mimetype) = $res;
$path = '../images/' . ($id % 256) . '/' . $name;
if (file_exists($path)) {
header('Content-type: ' . $mimetype); // e.g. image/png
readfile($path);
exit();
}
}
}
// if any error happened, then 404 - it's dirty
header("HTTP/1.0 404 Not Found");
echo 'sorry, we couldn\'t find this image';
?>
getImageByHash() would query the db.
this solution is slower, because the webserver can't serve images directly anymore.
and: i'd rather not store the images in the database. exports would get huge, backups a pain.