views:

340

answers:

6

First, I noticed there are many questions regarding this, lots marked as duplicate.

I eventually came to this one.

And the accepted answer for that question although partially solves my question, it doesn't answer all of it.

My question is, a user uploads an image. I store the path in the database and the image file in the file system. However, I make 3 copies of that image (large-, medium- and small-sized). So all in all I have 4 images - original, large, medium, small.

Should I store all 4 paths in the database, like so

ID  |      original      |    large        |    medium       |    small       |
----+--------------------+-----------------+-----------------+----------------+
 1  |  /path/to/original | /path/to/large/ | /path/to/medium | /path/to/small |

or just store the original's path, and give the other 3 a naming convention, like so: car.jpg, car.jpg, large-car.jpg, medium-car.jpg, small-car.jpg?

I feel this way would be less heavy on the database, and that if later, I wanted to add another size (ie. extra small) I wouldn't have to moditfy the database.

+7  A: 

If all the images in a given row live in the same place, I'd say their base path should be its own column (rather than re-deriving the base path from the original image's full path all the time).

If all the images in the database live in the same place, don't store the base path in this table at all; have it in code, or in a global configuration table.

chaos
Well, it's a blog. Each user has his/her own dir. each time the user makes a blog with pictures, i create a new dir with the blogID, and inside that dir i plan on storing all 4 images.
lyrae
Then what I would do is have a constant for the parent of all these directories, `define('BLOG_IMAGE_BASE_PATH', '/images/go/here')` or whatever, and, ideally, a method on the user object, `function getImagePath() { return BLOG_IMAGE_BASE_PATH . '/' . $this->blogID; }`, and assemble image paths from that.
chaos
+1  A: 

For sure have a solid naming convention for the various sizes of the original image, this will help you with generating known cache keys so you can store the images in some cache, like memcache, this relieves the load on the db and server's disk i/o

+2  A: 

Seems like you are trying to overuse the Database. How about this method instead.

ImageID  | UserID  | name.. 
---------+---------+-----
1        | 495     | car454.jpg
2        | 495     | house.jpg
3        | 44      | kittysmall.jpg

And Store all the images in one place.

IMAGES_PATH = "/path/to/images"

And name the images by the imageID (Auto Increment), so for the 5th image, it would be 5.ori.jpg or 5.large.jpg etc

This way you can easily see who owns what image, and also the user can upload different images with the same filename and not have to worry about that.

The Unknown
Interesting. But wouldnt this method actually be overusing the database? I mean, for every image uploaded, it would make 4 insert transactions. If user upload "car.jpg", i would resize that into large, medium and small. thus i would insert car.jpg, small-car.jpg, large-car.jpg and medium-car.jpg into the database; as opposed to just inserting "car.jpg", and when wanting to show all 4 images in the blog, i would just append "small-", "large-", "medium-" to the original image name( car.jpg)
lyrae
No lyrae, you'd still only use one insert. You'd insert "car.jpg" and select the auto-incremented ID as a result, let's say it returns "5". You'd then save "5-small.jpg", "5-medium.jpg" and "5-large.jpg".
X-Cubed
+1  A: 

To generalise, I'd say if you can recreate the information (because the base is always the same, followed by the users name), don't store it in the database. If you later want to change the directory where you store images for whatever reason, you'd be in trouble.

deceze
A: 

As a minor tweak, I'd be tempted to place the generated thumbnails, etc. in a different path (e.g.: ../generated/) to ensure that you don't overwrite the source image if someone uploads a file called 'car-large.jpg', etc.

middaparka
well, if someone uploads a file called "large-car.jpg", "large-" would be prepended,and it would become "large-large-car.jpg".
lyrae
+1  A: 

If the specific paths are consistent except for the file names why not use constants for the paths and then just store the different sized images in the appropriate directories and reference just the file names in the database.

The main principle here is avoiding duplicate information, in the database and in your code. For the database you achieve higher normal form, and for the code you achieve DRY (Don't Repeat Yourself).

Assume you structure is something like

/home/user/site/images/original/

/home/user/site/images/small/

/home/user/site/images/medium/

/home/user/site/images/large/

you could use constants for that info. e.g.

PATH_ORIGINAL = /home/user/site/images/original/

PATH_SMALL = /home/user/site/images/small/

PATH_MEDIUM = /home/user/site/images/medium/

PATH_LARGE = /home/user/site/images/large/

Then in your code you could do something like

smallcar = PATH_TO_SMALL . car.jpg;

Or just insert the appropriate constant variable inside whatever query output you have for loading the images.

The added benefit is that you have one place to change paths if you need to tweak directory structures or move code between servers, rather than update a whole slough of database records, which might be more problematic and error prone.

Gordon Potter
Images could be overwritten this way, no?
lyrae
whatever script is writing or creating the originals (I assume from a file upload process), have it make the image files set the permissions to read only once written. That should protect you from overwrites. But then you would have to error handle any attempt to write to a read only file. Another common technique is prepend a unique hash string to the beginning of the file name before saving. That way all new files are guaranteed to be unique names.But perhaps I am misunderstanding the original intent of your question.
Gordon Potter