7
votes

My AppEngine project has an API method that sends a resumable URL to an Android Client which then uses that resumable URL to upload an image.

I have another API method that create and returns a signed URL. In the Signed URL you must specify the Google Cloud Storage bucket and object name. However, that object may not exist, in which case, the signed URL will of course not work.

How can I quickly check if an object exists (in a bucket) in my App Engine backend before issuing the Signed URL?

EDIT: My App Engine project is a Cloud Endpoints project.

1
How did it disappear? :) If you know the object's name, it should be still there unless you deleted it yourself and forgot to update your database.Andrei Volgin
@AndreiVolgin I store a profile photo for users of my mobile app that looks something like "profile_photo_user_" + username in GCS. However, new users may not have yet uploaded a photo. Either way, I get their profile photo. So the signed URL could point to an image that doesn't exist yet. Given your comment is sounds like I need to rethink this strategy of storing/retrieving profile photos :) I just have no way of knowing when a user uploads an image via the resumable URL in order to write an entry to datastore of the obj name for example.Micro
Do you need a resumable upload for something so small as a profile photo? Resumable uploads are for files measured in many MBs or even GBs. It can be slower/less efficient for small files. If you use, instead, a getUploadUrl method, you will get a callback to your server with the file details after the upload is competed, and you can update the database at that point (e.g. set "photo available" to "true").Andrei Volgin

1 Answers

3
votes

You can call getMetadata to check if the object exists without downloading it.

GcsService fileService = GcsServiceFactory.createGcsService();
GcsFilename file = new GcsFilename(bucket, object);
fileService.getMetadata(file);

Alternatively, you can list all objects in a bucket or all objects in a bucket that start with the specified prefix (which can equal the object's name, if necessary).

UPDATE:

This is how I send uploadURL to my client:

@Override
public String getUploadUrl() throws LoginException, VersionException {
    // Verify that call is from a registered user and with proper headers

    BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
    String callbackUrl = "/blob";
    return blobstoreService.createUploadUrl(callbackUrl,
           UploadOptions.Builder.withGoogleStorageBucketName("myBucket));
}