Announcement Announcement Module
Collapse
No announcement yet.
Where a uploaded image file shall be store? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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

    Comment


    • #3
      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.

      Comment


      • #4
        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

        Comment


        • #5
          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.

          Comment


          • #6
            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

            Comment


            • #7
              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.

              Comment


              • #8
                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.

                Comment


                • #9
                  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

                  Comment


                  • #10
                    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.

                    Comment


                    • #11
                      Beware the BLOB (size limit)

                      As we all know, BLOB sizes are limited to 4GB, which will suit most of us, but not all. If you're dealing with large, large files, you're gonna have to judge whether it'll fit into a BLOB. Friendly caveat.

                      Comment


                      • #12
                        In my current project, we store all of our files in the filesystem and the references in the database.
                        What we did before choosing type of storage was:
                        1) Defined what types of images we had to deal with. With "types" I mean size.
                        2) How many images the system should be able to store.
                        3) Developed some test cases for storing as BLOB, BFILE(we use Oracle) or in the filesystem.

                        The tests showed that for very small images (<10k), BLOB was fastest. For images >10k<300k, BFILE and FS was best. For Images >300k, FS CLEARLY was the best!

                        First, most of ours pictures is quite big(>1Mb). That's one reason for us to choose FS for persistence.

                        Second, we have a LOT of images. For the moment, we have about 400 million of them and it increases with about 60-80 million per year.
                        If we should store all of the images in our database, well, we would get a REALLY BIG database to do backup(and maybe, restore) on!

                        Cheers

                        Comment


                        • #13
                          The main advantages of the filesystems (especially on linux machines) is that one can get a very advanced fs that supports journaling and is getting more and more close to db reliability. Ofc, one can't still do queries but as Wesslan pointed out, for files bigger then 300KB or for a large number of files, the advantages are compeling.
                          As for the 4GB limit - most filesystems have the same restriction; when dealing with such big data files, it's best to adjust the environment accordingly (imagine just what type of bandwidth is required to upload/download 4GB).

                          Comment


                          • #14
                            how to compress image file size

                            Is there a way to compress an image file size in Spring?
                            Sorry if this is way out of the thread, just can't get an answer to this.
                            Pls help

                            Comment


                            • #15
                              You can compress data in Java but it's not a Spring thing. Try googling it.
                              Last edited by karldmoore; Aug 27th, 2007, 02:36 PM.

                              Comment

                              Working...
                              X