1

so i have images in my S3. In android, i uploaded a new image to the same key in S3. In s3, the image did update correctly. But, when i pull that updated image from android using the Glide library with the image's URL, i get the last image file and not the updated one. I have no idea what setting I'm suppose to change in S3 to fix this! I hope someone can help!

Here is how i get my images from s3:

Glide.with(getBaseContext()).load("https://myBucketURL/" + username + "PROFILE_IMAGE").centerCrop().into(my_imageView);

How i upload images into s3:

  private void uploadToS3(String imagePath)
    {
        try
        {
            observer = transferUtility.upload(
                    "myBucket",     /* The bucket to upload to*/
                    username + "PROFILE_IMAGE",    /* The key for the uploaded object*/
                    imageStringToFile(imagePath,profileImageFile)        /* The file where the data to upload exists*/
            );
            observer.setTransferListener(new TransferListener()
            {
                @Override
                public void onStateChanged(int id, TransferState state) {
                    // do something
                }
                @Override
                public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
                    int percentage = (int) (bytesCurrent / bytesTotal * 100);
                    //Display percentage transfered to user
                }
                @Override
                public void onError(int id, Exception ex) {
                    // do something
                    Log.e(PROFILE_IMAGE,"error");
                    Log.d(PROFILE_IMAGE, ex.getMessage());
                }
            });
            success = true;
            Log.d(PROFILE_IMAGE,"upload success!");
        } catch (IOException e)
        {
            e.printStackTrace();
            Log.d(PROFILE_IMAGE,"upload failure");
            Log.d(PROFILE_IMAGE,e.getMessage());
            success = false;
        }
    }

    private File imageStringToFile(String path, String fileName) throws IOException //returns you an image file FROM the image string
    {
        Bitmap bitmapImage = BitmapFactory.decodeFile(path);
        //create a file to write bitmap data
        File f = new File(activity.getBaseContext().getCacheDir(), fileName);
        f.createNewFile();
        //Convert bitmap to byte array
        byte[] bitmapdata = ImageCompression.getInstant().getCompressedBitmap(path).toByteArray();
        //write the bytes in file
        FileOutputStream fos = new FileOutputStream(f);
        fos.write(bitmapdata);
        fos.flush();
        fos.close();
        return  f;
    }

Cheers!

TheQ
  • 1,770
  • 6
  • 33
  • 60
  • 1
    Are you waiting for some time to retrieve your image back? Please have a look at this question: http://stackoverflow.com/questions/23786609/what-is-maximum-amazon-s3-replication-time-on-file-upload – Manish Joshi Feb 08 '17 at 03:47
  • Do you have a CDN like CloudFront in front of the S3 bucket? – Mark B Feb 08 '17 at 03:53
  • hmm, i see. so for my use case, if a user changes their profile picture. What i try to do is over write their current picture but keep the same key. And since whenever they return to their profile screen, i need to go to that s3 link a delay would be really bad, because they would see that their image has not changed (even though in the backend it has). Is there no way to decrease that delay. Because even now if i close the app and open it again or wait 10 minutes its still the old profile image. – TheQ Feb 08 '17 at 03:54
  • @MarkB what is a CDN. I know the basics of S3 (upload and download) but not familiar with all its properties. Can you elaborate? – TheQ Feb 08 '17 at 03:55
  • Have you verified whether the new image works from a different browser or device? – Michael - sqlbot Feb 08 '17 at 04:23
  • After you upload, can you check that it is updated in the S3 console? Does `Glide` have a caching mechanism? If you don't know what a CDN is you probably didn't create one (assuming you created the bucket yourself). – donkon Feb 08 '17 at 04:28
  • @donkon Yes, i created the bucket myself. The default setting was set to versioning is off. So when i download the image onto my desktop, the image did update correctly. It might be the Glide caching i havent checked that. But i am open to suggestions on how to solve this problem – TheQ Feb 08 '17 at 04:35
  • I would recommend using the download API from the AWS SDK for Android. Sorry, I don't have any insight about how Glide works. – donkon Feb 08 '17 at 04:59

3 Answers3

1

Since you are getting the correct image uploaded in the S3 but not in the app, you may be try this solution with Glide to solve it.

Glide.with(getBaseContext())
.load("https://myBucketURL/" + username + "PROFILE_IMAGE")
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(my_imageView);

Note : Since you are keeping the same Url to load image in the imageview Glide is using the cached version of image to display the next time. So by removing cache in Glide can help solve your issue.

android_griezmann
  • 3,217
  • 3
  • 13
  • 39
  • yes that was the solution! I implemented it a different way which i will share soon. – TheQ Feb 08 '17 at 05:11
0

So the problem turned out that it was the glide library. You must dump its cache before uploading a new one.

  1. I first start a background thread using AsyncTask:

2.In that async task, i call removeGlideCache(), which removes the cache.

3.And then i upload the most recent s3 object in the onPostExecute() in the AsyncTask.

    class RemoveGlideCacheAsyncTask extends AsyncTask<Void,Void,Void>
    {
        @Override
        protected Void doInBackground(Void... params)
        {
            removeGlideCache();
            return null;
        }
        @Override
        public void onPostExecute(Void var)
        {
            Glide.with(getBaseContext()).load("my_bucket_url/"+"imageKey").centerCrop().signature(new StringSignature(String.valueOf(System.currentTimeMillis()))).into(nD_image);
        }
    }
    private void removeGlideCache()
    {
        Glide.get(Main.this).clearDiskCache();
    }
TheQ
  • 1,770
  • 6
  • 33
  • 60
0

All answers are correct. But they defeat the purpose of the cache that prevents making http request each time you want to show an image. Prefer using cache invalidation instead using a signature. This signature is like a hash that checks that your resource is in the cache (your url for example), if your signature is different, then Glide gets the image from the resource (url for your case) specified and updates the signature. You normally save the signature metadata (a lastUpdated timestamp is usually used) somewhere (if your image is an user image, then you can save a lastUpdatedImage timestamp on the User table) so you can compare each time you need to show an image.