ImagesService.getServingUrl fails with IllegalArgumentException and no error message for Cloud Storage object

804 views
Skip to first unread message

dennis

unread,
Jun 17, 2013, 4:02:10 PM6/17/13
to google-a...@googlegroups.com
Here's the code:

public static String getNotFoundUrl(int size) {
    try {
      BlobKey blob_key = BLOB_STORE.createGsBlobKey("/gs/web_content/placeholder_img.png");

      // Simple Test to make sure blob_key points at the right thing.
      byte[] image_data = BLOB_STORE.fetchData(blob_key, 0, 100);
      Application.getLogger().warning(new String(image_data));
      // This parts works and gets the first 100 bytes.

      ServingUrlOptions opts = ServingUrlOptions.Builder.withBlobKey(blob_key);
      if(size > 0) opts.imageSize(size);
      return IMAGES_SERVICE.getServingUrl(opts);
    } catch(IllegalArgumentException e) {
      Application.getLogger().warning("Unable to serve placeholder image from Cloud Storage.");
      Application.getLogger().warning(e.getMessage());
      Application.logException(e);
      return "/placeholder_img.png";
    }
  }

The fetchData call succeeds and I successfully read the first 100 bytes of the file that way. But the getServingUrl fails with IllegalArgumentException.

java.lang.IllegalArgumentException: 
at com.google.appengine.api.images.ImagesServiceImpl.getServingUrl(ImagesServiceImpl.java:282)

Any ideas on why this happens will be much appreciated.

Vinny P

unread,
Jun 17, 2013, 4:20:01 PM6/17/13
to google-a...@googlegroups.com
Hello Dennis,
 
Just to be clear the variable BLOB_STORE in your code represents the Files API accessing Google Cloud Storage, correct? Can you post that code as well? 
 
Secondly, if you are using Google Cloud Storage to save your images in, then you need to use a different function to create your ServingUrlOptions. Instead of using ServingUrlOptions.Builder.withBlobKey (which is reserved for images coming from AppEngine's Blobstore), you need to use ServingUrlOptions.Builder.withGoogleStorageFileName (files from GCS). Here's the relevant documentation:  https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/images/ServingUrlOptions.Builder .
 
 
-----------------
-Vinny P
Technology & Media Advisor
Chicago, IL

My Go side project: http://invalidmail.com/
 

dennis

unread,
Jun 17, 2013, 4:36:40 PM6/17/13
to google-a...@googlegroups.com
Thanks for the fast response Vinny,

Here are the definitions for the BLOB_STORE and IMAGES_SERVICE variables.

  private static final BlobstoreService BLOB_STORE = BlobstoreServiceFactory.getBlobstoreService();
  private static final ImagesService IMAGES_SERVICE = ImagesServiceFactory.getImagesService();

I have also tried using ServingUrlOptions.Builder.withGoogleStorageFileName with the same result of IllegalArgumentException with no error message.

  public static String getNotFoundUrl(int size) {
    try {
//      BlobKey blob_key = BLOB_STORE.createGsBlobKey("/gs/web_content/placeholder_img.png");
//      byte[] image_data = BLOB_STORE.fetchData(blob_key, 0, 100);
//      Application.getLogger().warning(new String(image_data));
      ServingUrlOptions opts = ServingUrlOptions.Builder.withGoogleStorageFileName("/gs/web_content/placeholder_img.png");
      if(size > 0) opts.imageSize(size);
      return IMAGES_SERVICE.getServingUrl(opts);
    } catch(IllegalArgumentException e) {
      Application.getLogger().warning("Unable to serve placeholder image from Cloud Storage.");
      Application.getLogger().warning(e.getMessage());
      Application.logException(e);
      return "/placeholder_img.png";
    }
  }

One interesting thing to note is that the file was uploaded using the Cloud Console Web UI and not through app engine sdk. Could that be what's causing the problem?

Vinny P

unread,
Jun 18, 2013, 1:19:17 AM6/18/13
to google-a...@googlegroups.com
Hello again Dennis,
 
On Mon, Jun 17, 2013 at 3:36 PM, dennis <dennis.k...@gmail.com> wrote:
One interesting thing to note is that the file was uploaded using the Cloud Console Web UI and not through app engine sdk. Could that be what's causing the problem?

 
Amusingly enough, that might be the problem. I configured my app to have Owner permissions over my Cloud Storage bucket - I noticed that when my app wrote an object in, it had full permissions to that object. If I uploaded an object via the Cloud Console, sometimes my app had difficulty accessing the object (even though my app had permissions to the bucket!).
 
I'm interested now - I'll have to investigate more. If you need it, here's a simplified version of the code I used to save to Cloud Storage:
 
  String bucket = bucket name here
  String object = the filename here, including file extension
  
  GcsFilename gcs_filename = new GcsFilename(bucket, object);
  
  GcsFileOptions.Builder options_builder = new GcsFileOptions.Builder();
  options_builder = options_builder.mimeType(mime);
//erased some options here
  GcsFileOptions options = options_builder.build();
  
  GcsOutputChannel output = GcsServiceFactory.createGcsService().createOrReplace(gcs_filename, options);
  output.write(ByteBuffer.wrap(data));
  output.close();  
 
 
On Mon, Jun 17, 2013 at 3:36 PM, dennis <dennis.k...@gmail.com> wrote:
Thanks for the fast response Vinny,
I have also tried using ServingUrlOptions.Builder.withGoogleStorageFileName with the same result of IllegalArgumentException with no error message.

  public static String getNotFoundUrl(int size) {
    try {
//      BlobKey blob_key = BLOB_STORE.createGsBlobKey("/gs/web_content/placeholder_img.png");
//      byte[] image_data = BLOB_STORE.fetchData(blob_key, 0, 100);
//      Application.getLogger().warning(new String(image_data));
      ServingUrlOptions opts = ServingUrlOptions.Builder.withGoogleStorageFileName("/gs/web_content/placeholder_img.png");
      if(size > 0) opts.imageSize(size);
      return IMAGES_SERVICE.getServingUrl(opts);
    } catch(IllegalArgumentException e) {
      Application.getLogger().warning("Unable to serve placeholder image from Cloud Storage.");
      Application.getLogger().warning(e.getMessage());
      Application.logException(e);
      return "/placeholder_img.png";
    }
  }
 
 
I built a test project to verify for myself, and the following code works for me on production GAE.
 
  String bucket = bucket name (so web_content for your example)
  String object = object name (placeholder_img.png for your example)
  
  //Get serving url
  String gs_blob_key = "/gs/" + bucket + "/" + object;
  BlobKey blob_key = BlobstoreServiceFactory.getBlobstoreService().createGsBlobKey(gs_blob_key);
  ServingUrlOptions serving_options = ServingUrlOptions.Builder.withBlobKey(blob_key);
  String serving_url = ImagesServiceFactory.getImagesService().getServingUrl(serving_options);
  System.out.println("Serving URL: " + serving_url);
  resp.getWriter().println(serving_url);
 
 
 
It's also worth double checking to see if you have permissions set correctly. Here's an image album showing my settings: http://imgur.com/a/FBhFN 

dennis

unread,
Jun 18, 2013, 1:38:10 AM6/18/13
to google-a...@googlegroups.com
Thanks Vinny!

Permissions were the culprit. 

On Monday, June 17, 2013 11:19:17 PM UTC-6, Vinny P wrote:
Hello again Dennis,

bk aaron

unread,
Jul 1, 2017, 11:16:25 AM7/1/17
to Google App Engine
am getting the same error "java.lang.IllegalArgumentException: INVALID_BLOB_KEY: Could not read blob.
 at com.google.appengine.api.images.ImagesServiceImpl.getServingUrl(ImagesServiceImpl.java:282)

i want to return the image url
here's the code

public List<String> blobstore_method(HttpServletRequest request) throws IOException{
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request);
        List<BlobKey> blobKeys = blobs.get("myFile");
        image_urls = null;

        if (blobKeys == null || blobKeys.isEmpty()) {
            response.sendRedirect("/");
        } else {
            response.sendRedirect("/notice.jsp");
            System.out.println("submited");
        }       
        for(BlobKey obj : blobKeys){
obj.getKeyString();
//blobstore image
com.google.appengine.api.images.ImagesService services = ImagesServiceFactory.getImagesService();
ServingUrlOptions serve = ServingUrlOptions.Builder.withGoogleStorageFileName("/gs/"+obj.getKeyString());      // Blobkey of the image uploaded to BlobStore.
image_urls.add(services.getServingUrl(serve));
}
        return image_urls;
}

mao hieng

unread,
May 29, 2018, 10:30:35 AM5/29/18
to Google App Engine
java.lang.IllegalArgumentException: INVALID_BLOB_KEY: Could not read blob.
at com.google.appengine.api.images.ImagesServiceImpl.getServingUrl(ImagesServiceImpl.java:282)

As my 3 projects experience, this error occurs on the local dev server only. It will return a success serving URL on the production server.

Hope this could help.
Reply all
Reply to author
Forward
0 new messages