Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: Where a uploaded image file shall be store?

  1. #1

    Default 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 "Pro Spring" 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.

  2. #2
    Join Date
    Jul 2005
    Location
    Idaho
    Posts
    231

    Default

    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

  3. #3
    Join Date
    Aug 2004
    Location
    Sydney
    Posts
    503

    Default

    Something that you should do in either case is make sure you implement code to send back the HTTP 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.

  4. #4

    Default

    Steve O,

    You mentioned the following in the post above:

    Quote 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

  5. #5
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    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.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  6. #6
    Join Date
    Jul 2005
    Location
    Idaho
    Posts
    231

    Default

    I use what I think is somewhat of an outdated method (in an ImageUtils class):
    Code:
     
        public void createThumb(HttpServletRequest request, File thumbFile, File savedFile)
        {
           try
           {
              // load image from the savedFile (the original jpeg uploaded)
              Image image = Toolkit.getDefaultToolkit().getImage(savedFile.toURL());
              // MediaTracker to track the status of media objects
              MediaTracker mediaTracker = new MediaTracker(new Container());
              mediaTracker.addImage(image, 1);
              mediaTracker.waitForID(1);
              logger.info("### mediatracker done");
              // 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 < 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("### image drawn");
              // 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("### Exception " + 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

  7. #7

    Default

    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.

  8. #8

    Default

    Quote Originally Posted by matthewramella
    Steve 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.

  9. #9
    Join Date
    Jul 2005
    Location
    Idaho
    Posts
    231

    Default

    VW - yes, it gets the dimensions of the original and the h & 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

  10. #10
    Join Date
    Aug 2005
    Posts
    28

    Default

    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •