7

I have a website where users each have their own profile page. Here they can upload a single image that acts as their avatar. This is the only image users can upload to the server across the whole site. There is no archive so it can be overwritten if a user wishes to update their avatar.

I have never had to do anything like this before so I would like to open it up and ask for a suitable, scalable option for this website.

My initial thought is to give each user's image a random name, a string 6-12 characters long. This way you couldn't build a script that just pulls every user's profile pic from a directory (eg 001.png, 002.png etc). My second thought is that there should be only be a certain amount of images per directory to make sure they can be retrieved quickly by the server.

There may well be other things I'm missing here, I'm not sure on exact details hence why I'm asking.

jskidd3
  • 4,609
  • 15
  • 63
  • 127
  • 2
    Simple, rename the file to an MD5 of the user's username. You don't have to worry about weird characters in their username like spaces or accented characters, it's fast, unique per-user, constant, and difficult to guess. – Sammitch Dec 16 '13 at 22:42
  • For scalability, I would advise using a CDN/storage service - like amazon s3. There are a lot of scripts out there for integrating with PHP. It would take the load off of your web server when the files are served. It is also super cost effective or as I call it - cheap. – picus Dec 16 '13 at 22:42
  • What about integrating [Gravatars](https://gravatar.com)? – DaSourcerer Dec 16 '13 at 22:44
  • Hi there. On Stack Overflow, there tends to be a policy of [snipping salutations and advance thanks](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts) on posts. It's not a big deal - it's just for brevity and clarity. When writing, think more "text for posterity" than "forum" `:)`. – halfer Dec 16 '13 at 22:57
  • @halfer I appreciate that but I honestly don't totally agree with it. I like to thank the people that put time into reading and answering my questions rather than removing a line for those looking for answers – jskidd3 Dec 16 '13 at 22:59
  • @jskidd3: Thank them later, as a comment. ;-) – SilverlightFox Dec 17 '13 at 23:59
  • @Sammitch: You might want to add a "salt" in there if you're bothered about anyone using your image files to achieve user enumeration. https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002) – SilverlightFox Dec 18 '13 at 00:08

3 Answers3

4

I would recommend storing the images on something like Amazon S3. Depending on how many pictures you're storing, serving images can really take a tow on your web server. S3 is scalable and with multi-zone deployments through CloudFront (Amazon's version of a CDN), you can really speed up this part of your service.

Lloyd Banks
  • 35,740
  • 58
  • 156
  • 248
2

It's good idea to not overload single directory. Very often you can see that images are stored in hierarchy of folders according to theirs first few letters. An example of this is

b5dcv5.jpg -> /b/5/b5dcv5.jpg
bsgb0g.jpg -> /b/s/bsgb0g.jpg
a5dcbt.jpg -> /a/5/a5dcbt.jpg

and so on. I thing you got the principle. Advantage of this is to have access to and image in O(log N) when filenames are uniformly distributed instead of O(N) as it would be in single folder solution.

tomas789
  • 1,280
  • 1
  • 9
  • 21
  • 2
    You probably don't need to do this on a modern filesystem. Ext3 (Linux) filesystems will use O(log N) HTrees instead of simple lists once directories grow large. The story with NTFS is [a bit more interesting](http://stackoverflow.com/questions/197162/ntfs-performance-and-large-volumes-of-files-and-directories) but still certainly good for hundreds of thousands of files. – bobince Dec 17 '13 at 00:09
0

I've been using base64 to store them within an SQL database. No need to manage files. It works well for relatively low resolution options.

How about not storing them as images at all? You could leverage an external placeholder for each user, you could cache a random image from lorempixel.com: http://lorempixel.com/100/100. Use an MD5 hash of the user's name or ID. You could also just save the image using the user's ID, for example 442.jpg.

Ahmed Sagarwala
  • 400
  • 2
  • 13