0

I am developing a website using Yii framework. On my website I have user profiles (already implemented). I will have a file uploader so that users can upload profile images. Some profiles may be available to the public, others will be private. Private profiles should be inaccessible to public users, and the images on this profile may not be accessible to anyone except for the owner of the profile.

I have read that it is a bad idea to store images in a MySQL database as it kills performance and may be disallowed on my webhosts. I have thought of storing the images in my protected directory, but if done here, I will not be able to link to the images at all. How then will I be able to display images on valid profiles (public profiles, or profiles belonging to the user?)

Any hint or idea will be greatly appreciated (related to Yii, php or any other). Let me know if my question is unclear. Thank you.

*BTW, I have never had a formal web development course, and like many others I have learnt everything I know in my own time, so it's very possible that I am missing a very simple/obvious solution.

Denzil
  • 664
  • 1
  • 8
  • 20
  • 1
    sounds like it's an implementation of your arhcitecture you need to address. You should be storing the type of user they are, private or public, and then checking that when a viewer attempts to view someone's profile. If they are not logged in as the (private) user of the profile they are trying to view, don't show them anything. – thescientist Feb 28 '12 at 18:50
  • Thanks for the reply. I guess I was not completely clear on this. I have already implemented it as you have suggested (with private and public users. And users who hack the url, are sent away to some error page/access denied page). However, I am worried that it may still be possible for "clever" users to access private user's images through some url hack (since the images are stored in public domain). And as stated above, the reason why I don't want to store it in protected domain is that I will not be able to display the images at all on user pages, but perhaps I am wrong in thinking this? – Denzil Feb 28 '12 at 19:02

3 Answers3

2

serve the images thru a php file that can check whether they current session has permissions

miki
  • 695
  • 3
  • 8
2

After user uploaded his pic, rename the image randomly and store the random file name in user table.

After the user logged in, you will of course set the session (at least user id).

Create image_profile.php and get the user_id from session in that file. After that, execute such a query:

SELECT `profile_image_filename`
FROM user WHERE user.id = {$SESSION['user_id']}
LIMIT 1;

and then send {$profile_image_filename}.jpg so that the result of image_profile.php will be profile image of the logged in user. (How to output an image dynamically? Output an Image in PHP)

Community
  • 1
  • 1
Mohammad Naji
  • 5,372
  • 10
  • 54
  • 79
  • This sounds like something I will be able to do without too much work in terms of learning on my behalf. Thanks for the help! – Denzil Feb 28 '12 at 20:35
  • 1
    rather than randomizing the file name, store the image at an inaccessible path that the server can read from, then it'll truly be "private" – miki Feb 28 '12 at 21:29
1

After user uploads the image, get the random image name, eg. mt_rand(30,999) . imageExtension.
Store this value as user image name in the image table. Images table contains it's own id, user_id, and the name columns.

In Yii Image model create protected function afterSave() method which will store your image on the filesystem. Your real image name in the filesystem will consist of the image id in the database and the image name from the database.
Do not forget to add followin line to this function:

return parent::afterSave();

Example:
You have jpg image called me.jpg
mt_rand(30,999) gives us 421
So you store your jpg image in the database.
The row has values:
id=7, user_id=3, name=421.jpg
Now you save the image under the name 7_421.jpg.
By doing it your image will never get the same name twice, since the id we use in the first part of the image name is unique. Moreover, nobody will know the name of the image, because she/he will need both id and random number.

To display image only for the owner you compare logged user id is the same as the user_id by doing:

if(Yii::app()->user->id === $image->user_id) {
 // display photo
}

You don't need to take care of the session. Yii does for you.

Jakub
  • 393
  • 1
  • 4
  • 18
  • Hmm thanks. I already have it working but in a slightly different way. I am accepting your answer though as you seemed to have put a lot of thought into it and it's the clearest in my opinion. In my current implementation I save my images out of the reach of the public domain, and then serve the images through a php file. I think I'll change it a bit so that it's more like this though (in the end it has to be up to a certain extent). – Denzil Feb 29 '12 at 17:07