|
|
Where a uploaded image file shall be store?
A few of years ago, I was told that a user uploaded image file should be stored in the server file system, but not in the DB. The image file path on the server should be stored in the DB instead. I used this approach for a Java web application at the time.
When I study the Spring sample applications, I find that all image files are stored in DB. The image DB sample application came with the Spring distribution and the sample application of the quot ro Springquot; use the same approach. Can someone tell me the pros and cons of these two approachs? I know no all DBs can handle BLOB well.
Thanks.
Yes, I too would like to know the cons (or pros) of the way you do it. Currently, I have an application where a user uploads an image (commons fileupload), the application resizes it, makes a thumbnail and stores that in a separate folder. Only the name go to the database - very fast. This works for me for portability too.
Although it works, it seems that blobbing it would be the 'correct' way to go.
Steve O
Something that you should do in either case is make sure you implement code to send back the from 304 (Not Modified) code when possible.
This tells the browser to get the image from its cache.
The optimisation to return a 304 code is something that could possibly be added to the Spring framework, maybe as an Interceptor or something for when the application is handling the supply of images, etc.
An upside of storing images in the DB is that for clustered apps, it's simpler to retrieve images. i.e. storing images in the file system for clustered apps means an extra config item to manage.
Steve O,
You mentioned the following in the post above:Originally Posted by Steve O
the application resizes it
Out of curiosity, how does the app resize the image? I have a situation where I'd like to reduce/compress the image size way down to about 100 kb's or so, before I save it to the server. I don't mind if the image loses it's quality.
Are there any open source utilities out there that automatically compress images?
Thanks,
Matt
One of the main reasons for storing images to the database is that you have transactional support. In most cases, the image is updated/stored along with other information (like name or login numbers) and so on.
FileSystems are not transactions and in case of an exception you can't really rollback - you can try to delete the files but overall you is not that easy and there are cases where you might be left with random files.
I use what I think is somewhat of an outdated method (in an ImageUtils class):
Code: public void createThumb(fromServletRequest request, File thumbFile, File savedFile) { try { // load image from the savedFile (the original jpeg uploaded) Image image = Toolkit.getDefaultToolkit().getImage(savedFile.toucl()); // MediaTracker to track the status of media objects MediaTracker mediaTracker = new MediaTracker(new Container()); mediaTracker.addImage(image, 1); mediaTracker.waitForID(1); logger.info(quot;### mediatracker donequot;); // set the thumbnail's width and height int thumbWidth = 125; int thumbHeight = 125; // sets ratio of widht to height double thumbRatio = (double)thumbWidth / (double)thumbHeight; // get the width and height of the original image int imageWidth = image.getWidth(null); int imageHeight = image.getHeight(null); // get the ratio of the original image double imageRatio = (double)imageWidth / (double)imageHeight; // set the height or width to preserve the ratio of the original image if (thumbRatio lt; imageRatio) { thumbHeight = (int)(thumbWidth / imageRatio); }else{ thumbWidth = (int)(thumbHeight * imageRatio); } // draw original image to thumbnail image object and // scale it to the new size on-the-fly BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = thumbImage.createGraphics(); graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null); logger.info(quot;### image drawnquot;); // save thumbnail image to thumbFile BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(thumbFile)); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(thumbImage); // set the quality of the thumb (100 being full quality) int quality = 100; quality = Math.max(0, Math.min(quality, 100)); param.setQuality((float)quality / 100.0f, false); encoder.setJPEGEncodeParam(param); encoder.encode(thumbImage); // close the output stream after it is saved out.close(); }catch(Exception e){logger.info(quot;### Exception quot; + e); } }I got that from the Sun website quite awhile ago... I think there are more modern ways to do it, but this works for me.
Like Costin warns, if there is an error, you can end up with some space garbage on your server. In my case, pictures are uploaded with other information... if there is an error (random file), then the admin will go back to the form and see the errors and make those corrections, the random file gets overwritten then.
Good luck!
Steve O
I recall that an image file name is retained during the file upload with the file system storage approach. And resizing image file is a must in the application since the sizes of each uploaded file vary, and almost all of images will get resized when thumbnail images are created to display a list of entries. The resized images are automatically created by a tag back by a piece of utility code shown as what Steve provides here, I believe. These resized image files are stored in the same location as the original ones. That seem to be quite easy with the appraoch. I don't know how well this resizing task works with the DB storage approach.
I am not aware of any image uploading problem due to a transaction issue with the file system approach.
Originally Posted by matthewramellaSteve O,
You mentioned the following in the post above:
Out of curiosity, how does the app resize the image? I have a situation where I'd like to reduce/compress the image size way down to about 100 kb's or so, before I save it to the server. I don't mind if the image loses it's quality.
Are there any open source utilities out there that automatically compress images?
Thanks,
Matt
I believe the resizing code takes the parameter of the width and/or height of the original image, but not the physical size.
VW - yes, it gets the dimensions of the original and the h amp; w can be set for the 'final' image - also the quality. I am not sure what the images are used for, but I have not had a need for print quality with this method; leaving it set to the highest setting works just fine for me.
As far as the size of the file, you should be able to check the size via FileUpload. From there, you should be able to pass along parameters to a method similar to my last post to target the 100k file.
The name is carried in FileItem.getString(). Changing the name would be a bad plan - the original will just hang out on the server! A couple of things to watch out for with this method:
unless you check the server for the newly uploaded file's name, a subsequently uploaded file of the same name (ie 'logo.jpg') will overwrite the original!
Also: IE Explorer - if you will believe that!
Good Luck,
Steve O
I would say it is good practice to never store uploaded files on a filesystem by their supplied name. You should use logical names which meet whatever uniqueness criteria is necessary for the way you've chosen to organize them. Then keep the original name in a database table, and if you're pedantic maybe mimic creation/modified/owner/permission fields too.
Any user supplied string should be considered unsafe and consideration should be given as to what you do with them.
The site I am currently working on is based entirely around uploads and downlonads (it's an analysis service performed on datafiles) and I just got through moving from a filesystem approach to blobs.
I have to admit I find the different binary data treatments of the various database vendors annoying, and there are some technical hitches handling blobs, like running out of memory if you're not careful. I've also found submissions take noticably longer to complete, enough so that I am a little concerned about impatient users cancelling it.
I'd also check that your chosen database vendor doesn't have a bizarre limit on table size that is incompatible with what you think your likely data retention requirements will be.
Still, I like the fact that supporting machines behind the webserver now just need tcp access for all their needs, I really disliked setting up remote file access. |
|